diff --git a/src/mako/cli/lib/cli.py b/src/mako/cli/lib/cli.py index 1eb3253444..4b99468a57 100644 --- a/src/mako/cli/lib/cli.py +++ b/src/mako/cli/lib/cli.py @@ -59,6 +59,22 @@ JSON_TYPE_RND_MAP = {'boolean': lambda: str(bool(randint(0, 1))).lower(), 'int64' : lambda: randint(-101, -1), 'string': lambda: '%s' % choice(util.words).lower()} +JSON_TYPE_TO_ENUM_MAP = {'boolean' : 'Boolean', + 'integer' : 'Int', + 'number' : 'Float', + 'uint32' : 'Int', + 'double' : 'Float', + 'float' : 'Float', + 'int32' : 'Int', + 'any' : 'String', # TODO: Figure out how to handle it. It's 'interface' in Go ... + 'int64' : 'Int', + 'uint64' : 'Uint', + 'string' : 'String'} + +CTYPE_TO_ENUM_MAP = {CTYPE_POD: 'Pod', + CTYPE_ARRAY: 'Vec', + CTYPE_MAP: 'Map'} + JSON_TYPE_VALUE_MAP = {'boolean': 'false', 'integer' : '-0', 'uint32' : '0', diff --git a/src/mako/cli/lib/engine.mako b/src/mako/cli/lib/engine.mako index bf6e206720..936a835954 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -8,7 +8,8 @@ call_method_ident, POD_TYPES, opt_value, ident, JSON_TYPE_VALUE_MAP, KEY_VALUE_ARG, to_cli_schema, SchemaEntry, CTYPE_POD, actual_json_type, CTYPE_MAP, CTYPE_ARRAY, application_secret_path, DEBUG_FLAG, DEBUG_AUTH_FLAG, CONFIG_DIR_FLAG, req_value, MODE_ARG, - opt_values, SCOPE_ARG, CONFIG_DIR_ARG, DEFAULT_MIME, field_vec, comma_sep_fields) + opt_values, SCOPE_ARG, CONFIG_DIR_ARG, DEFAULT_MIME, field_vec, comma_sep_fields, JSON_TYPE_TO_ENUM_MAP, + CTYPE_TO_ENUM_MAP) v_arg = '<%s>' % VALUE_ARG SOPT = 'self.opt' @@ -32,7 +33,7 @@ %>\ 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}; + calltype_from_str, remove_json_null_values, ComplexType, JsonType, JsonTypeInfo}; use std::default::Default; use std::str::FromStr; @@ -386,14 +387,16 @@ for kvarg in ${opt_values(KEY_VALUE_ARG)} { continue; } - let field_type = + let type_info = match &temp_cursor.to_string()[..] { % for schema, fe, f in schema_fields: <% pname = FIELD_SEP.join(mangle_subcommand(t[1]) for t in f) ptype = actual_json_type(f[-1][1], fe.actual_property.type) + jtype = 'JsonType::' + JSON_TYPE_TO_ENUM_MAP[ptype] + ctype = 'ComplexType::' + CTYPE_TO_ENUM_MAP[fe.container_type] %>\ - "${pname}" => Some("${ptype}"), + "${pname}" => Some(JsonTypeInfo { jtype: ${jtype}, ctype: ${ctype} }), % endfor # each nested field _ => { let suggestion = FieldCursor::did_you_mean(key, &${field_vec(sorted(fields))}); @@ -401,8 +404,8 @@ for kvarg in ${opt_values(KEY_VALUE_ARG)} { None } }; - if let Some(field_type) = field_type { - temp_cursor.set_json_value(&mut object, value.unwrap(), field_type); + if let Some(type_info) = type_info { + temp_cursor.set_json_value(&mut object, value.unwrap(), type_info); } } let mut ${request_prop_name}: api::${request_prop_type} = json::value::from_value(object).unwrap(); diff --git a/src/rust/cli/cmn.rs b/src/rust/cli/cmn.rs index c7299f5f15..c11a7f325c 100644 --- a/src/rust/cli/cmn.rs +++ b/src/rust/cli/cmn.rs @@ -17,6 +17,33 @@ use std::default::Default; const FIELD_SEP: char = '.'; + +pub enum ComplexType { + Pod, + Vec, + Map, +} + + // Null, + // Bool(bool), + // I64(i64), + // U64(u64), + // F64(f64), + // String(String), + +pub enum JsonType { + Boolean, + Int, + Uint, + Float, + String, +} + +pub struct JsonTypeInfo { + pub jtype: JsonType, + pub ctype: ComplexType, +} + // 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) { @@ -199,8 +226,27 @@ impl FieldCursor { } } - pub fn set_json_value(&self, object: &mut json::value::Value, value: &str, value_type: &str) { - + pub fn set_json_value(&self, object: &mut json::value::Value, value: &str, + type_info: JsonTypeInfo) { + assert!(self.0.len() > 0); + + for field in &self.0[..self.0.len()-1] { + object = match *object { + json::value::Value::Object(ref mut mapping) => { + mapping.entry(field.to_owned()).or_insert( + json::value::Value::Object(Default::default()) + ) + }, + _ => panic!("We don't expect non-object Values here ...") + } + } + + match *object { + json::value::Value::Object(ref mut mapping) => { + + } + _ => unreachable!() + } } pub fn num_fields(&self) -> usize {