diff --git a/src/mako/api/lib/schema.mako b/src/mako/api/lib/schema.mako index 01e6810c65..2920f441f1 100644 --- a/src/mako/api/lib/schema.mako +++ b/src/mako/api/lib/schema.mako @@ -2,7 +2,7 @@ from util import (schema_markers, rust_doc_comment, mangle_ident, to_rust_type, put_and, IO_TYPES, activity_split, enclose_in, REQUEST_MARKER_TRAIT, mb_type, indent_all_but_first_by, NESTED_TYPE_SUFFIX, RESPONSE_MARKER_TRAIT, split_camelcase_s, METHODS_RESOURCE, unique_type_name, - PART_MARKER_TRAIT, canonical_type_name, TO_PARTS_MARKER, UNUSED_TYPE_MARKER) + PART_MARKER_TRAIT, canonical_type_name, TO_PARTS_MARKER, UNUSED_TYPE_MARKER, is_schema_with_optionals) default_traits = ('RustcEncodable', 'Clone', 'Default') %>\ @@ -63,15 +63,11 @@ ${struct}; if 'variant' not in s: traits.insert(0, 'Default') - allow_optionals = True if RESPONSE_MARKER_TRAIT in markers: traits.append('Deserialize') nt_markers = schema_markers(s, c, transitive=False) - if ( PART_MARKER_TRAIT in nt_markers - or RESPONSE_MARKER_TRAIT in nt_markers and REQUEST_MARKER_TRAIT not in nt_markers): - allow_optionals = False - # use optionals only when needed + allow_optionals = is_schema_with_optionals(nt_markers) # waiting for Default: https://github.com/rust-lang/rustc-serialize/issues/71 if s.type == 'any': diff --git a/src/mako/cli/lib/cli.py b/src/mako/cli/lib/cli.py index 143b67e3f3..a4136bd180 100644 --- a/src/mako/cli/lib/cli.py +++ b/src/mako/cli/lib/cli.py @@ -4,7 +4,7 @@ import os import re import collections from copy import deepcopy -from random import (randint, random, choice, seed) +from random import (randint, random, choice) SPLIT_START = '>>>>>>>' SPLIT_END = '<<<<<<<' diff --git a/src/mako/cli/lib/engine.mako b/src/mako/cli/lib/engine.mako index 556410b691..b4d3769821 100644 --- a/src/mako/cli/lib/engine.mako +++ b/src/mako/cli/lib/engine.mako @@ -1,7 +1,7 @@ <%namespace name="util" file="../../lib/util.mako"/>\ <%! from util import (hub_type, mangle_ident, indent_all_but_first_by, activity_rust_type, setter_fn_name, ADD_PARAM_FN, - upload_action_fn) + upload_action_fn, is_schema_with_optionals, schema_markers) from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG, CONFIG_DIR, SCOPE_FLAG, is_request_value_property, FIELD_SEP, docopt_mode, FILE_ARG, MIME_ARG, OUT_ARG, cmd_ident, call_method_ident, arg_ident, POD_TYPES, flag_ident, ident, JSON_TYPE_VALUE_MAP, @@ -238,13 +238,21 @@ ${value_unwrap}\ % endif # handle call parameters % if mc.request_value: <% + allow_optionals_fn = lambda s: is_schema_with_optionals(schema_markers(s, c, transitive=False)) + def flatten_schema_fields(schema, res, cur=list()): if len(cur) == 0: cur = list() + + opt_access = '.as_mut().unwrap()' + if not allow_optionals_fn(schema): + opt_access = '' for fn, f in schema.fields.iteritems(): - cur.append(fn) + + cur.append(['%s%s' % (mangle_ident(fn), opt_access), fn]) if isinstance(f, SchemaEntry): - res.append((f, list(cur))) + cur[-1][0] = mangle_ident(fn) + res.append((schema, f, list(cur))) else: flatten_schema_fields(f, res, cur) cur.pop() @@ -261,35 +269,40 @@ for kvarg in ${SOPT + arg_ident(KEY_VALUE_ARG)}.iter() { err.issues.push(field_err); } match &field_name.to_string()[..] { - % for fv, f in schema_fields: + % for schema, fe, f in schema_fields: <% # TODO: Deduplicate ! - ptype = fv.actual_property.type - if ptype == 'string' and 'Count' in f[-1]: + ptype = fe.actual_property.type + if ptype == 'string' and 'Count' in f[-1][1]: ptype = 'int64' value_unwrap = 'value.unwrap_or("%s")' % JSON_TYPE_VALUE_MAP[ptype] - pname = FIELD_SEP.join(mangle_subcommand(ft) for ft in f) + pname = FIELD_SEP.join(mangle_subcommand(t[1]) for t in f) - struct_field = 'request.' + '.'.join('%s.as_mut().unwrap()' % mangle_ident(ft) for ft in f[:-1]) - if len(f) > 1: - struct_field += '.' - struct_field += mangle_ident(f[-1]) + allow_optionals = True + opt_prefix = 'Some(' + opt_suffix = ')' + if not allow_optionals_fn(schema): + opt_prefix = opt_suffix = '' + + struct_field = 'request.' + '.'.join(t[0] for t in f) %>\ "${pname}" => { - % if fv.container_type == CTYPE_POD: - ${struct_field} = Some(\ + % if fe.container_type == CTYPE_POD: + ${struct_field} = ${opt_prefix}\ % else: - if ${struct_field}.is_none() { - ${struct_field} = Some(Default::default()); - } - ${struct_field}.as_mut().unwrap().push(\ + ${struct_field}.push(\ % endif % if ptype != 'string': arg_from_str(${value_unwrap}, err, "${pname}", "${ptype}")\ % else: ${value_unwrap}.to_string()\ % endif -); + % if fe.container_type == CTYPE_POD: +${opt_suffix}\ + % else: +)\ + % endif +; }, % endfor # each nested field _ => { diff --git a/src/mako/lib/util.py b/src/mako/lib/util.py index 46c14531a9..0bcd6307f4 100644 --- a/src/mako/lib/util.py +++ b/src/mako/lib/util.py @@ -448,6 +448,9 @@ def schema_markers(s, c, transitive=True): ## -- End Rust TypeSystem -- @} +def is_schema_with_optionals(schema_markers): + return not (PART_MARKER_TRAIT in schema_markers + or RESPONSE_MARKER_TRAIT in schema_markers and REQUEST_MARKER_TRAIT not in schema_markers) # ------------------------- ## @name Activity Utilities