From ca36dbc50595f116952a95395d802d5be313b614 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 13 May 2015 08:45:57 +0200 Subject: [PATCH] feat(config): improved structure setter code We save about 30% of CLI code just because we offload the work of settings structures into serde, building a generic `json::Value` to contain all the data, and then let serde do the deserialization for us. All we need for that is some information we let the generator provide and translate it into the runtime. Closes #111 --- src/mako/cli/lib/engine.mako | 7 ++++--- src/rust/cli/cmn.rs | 21 ++++++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/mako/cli/lib/engine.mako b/src/mako/cli/lib/engine.mako index d118a6f266..661d3c63db 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -392,11 +392,12 @@ for kvarg in ${opt_values(KEY_VALUE_ARG)} { % for schema, fe, f in schema_fields: <% pname = FIELD_SEP.join(mangle_subcommand(t[1]) for t in f) + sname = FIELD_SEP.join(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(JsonTypeInfo { jtype: ${jtype}, ctype: ${ctype} }), + "${pname}" => Some(("${sname}", JsonTypeInfo { jtype: ${jtype}, ctype: ${ctype} })), % endfor # each nested field _ => { let suggestion = FieldCursor::did_you_mean(key, &${field_vec(sorted(fields))}); @@ -404,8 +405,8 @@ for kvarg in ${opt_values(KEY_VALUE_ARG)} { None } }; - if let Some(type_info) = type_info { - temp_cursor.set_json_value(&mut object, value.unwrap(), type_info, err); + if let Some((field_cursor_str, type_info)) = type_info { + FieldCursor::from(field_cursor_str).set_json_value(&mut object, value.unwrap(), type_info, err, &temp_cursor); } } 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 79aad3f223..d4d131f762 100644 --- a/src/rust/cli/cmn.rs +++ b/src/rust/cli/cmn.rs @@ -122,6 +122,14 @@ impl ToString for FieldCursor { } } +impl From<&'static str> for FieldCursor { + fn from(value: &'static str) -> FieldCursor { + let mut res = FieldCursor::default(); + res.set(value).unwrap(); + res + } +} + impl FieldCursor { pub fn set(&mut self, value: &str) -> Result<(), CLIError> { if value.len() == 0 { @@ -229,7 +237,8 @@ impl FieldCursor { pub fn set_json_value(&self, mut object: &mut Value, value: &str, type_info: JsonTypeInfo, - err: &mut InvalidOptionsError) { + err: &mut InvalidOptionsError, + orig_cursor: &FieldCursor) { assert!(self.0.len() > 0); for field in &self.0[..self.0.len()-1] { @@ -267,7 +276,9 @@ impl FieldCursor { match type_info.ctype { ComplexType::Pod => { - mapping.entry(field.to_owned()).or_insert(to_jval(value, type_info.jtype, err)); + if mapping.insert(field.to_owned(), to_jval(value, type_info.jtype, err)).is_some() { + err.issues.push(CLIError::Field(FieldError::Duplicate(orig_cursor.to_string()))); + } }, ComplexType::Vec => { match *mapping.entry(field.to_owned()) @@ -282,9 +293,9 @@ impl FieldCursor { match *mapping.entry(field.to_owned()) .or_insert(Value::Object(Default::default())) { - Value::Object(ref mut map) => { - if map.insert(key.to_owned(), jval).is_some() { - err.issues.push(CLIError::Field(FieldError::Duplicate(self.to_string()))); + Value::Object(ref mut value_map) => { + if value_map.insert(key.to_owned(), jval).is_some() { + err.issues.push(CLIError::Field(FieldError::Duplicate(orig_cursor.to_string()))); } } _ => unreachable!()