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
This commit is contained in:
Sebastian Thiel
2015-05-13 08:45:57 +02:00
parent d0b69af413
commit ca36dbc505
2 changed files with 20 additions and 8 deletions

View File

@@ -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();

View File

@@ -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!()