@@ -125,6 +125,87 @@ static bool BoxedType(const ::capnp::Type& type)
125125 type.isFloat64 () || type.isEnum ());
126126}
127127
128+ struct Field
129+ {
130+ ::capnp::StructSchema::Field param;
131+ bool param_is_set = false ;
132+ ::capnp::StructSchema::Field result;
133+ bool result_is_set = false ;
134+ int args = 0 ;
135+ bool retval = false ;
136+ bool optional = false ;
137+ bool requested = false ;
138+ bool skip = false ;
139+ kj::StringPtr exception;
140+ };
141+
142+ struct FieldList
143+ {
144+ std::vector<Field> fields;
145+ std::map<kj::StringPtr, int > field_idx; // name -> args index
146+ bool has_result = false ;
147+
148+ void addField (const ::capnp::StructSchema::Field& schema_field, bool param)
149+ {
150+ if (AnnotationExists (schema_field.getProto (), SKIP_ANNOTATION_ID)) {
151+ return ;
152+ }
153+
154+ auto field_name = schema_field.getProto ().getName ();
155+ auto inserted = field_idx.emplace (field_name, fields.size ());
156+ if (inserted.second ) {
157+ fields.emplace_back ();
158+ }
159+ auto & field = fields[inserted.first ->second ];
160+ if (param) {
161+ field.param = schema_field;
162+ field.param_is_set = true ;
163+ } else {
164+ field.result = schema_field;
165+ field.result_is_set = true ;
166+ }
167+
168+ if (!param && field_name == kj::StringPtr{" result" }) {
169+ field.retval = true ;
170+ has_result = true ;
171+ }
172+
173+ GetAnnotationText (schema_field.getProto (), EXCEPTION_ANNOTATION_ID, &field.exception );
174+
175+ int32_t count = 1 ;
176+ if (!GetAnnotationInt32 (schema_field.getProto (), COUNT_ANNOTATION_ID, &count)) {
177+ if (schema_field.getType ().isStruct ()) {
178+ GetAnnotationInt32 (schema_field.getType ().asStruct ().getProto (),
179+ COUNT_ANNOTATION_ID, &count);
180+ } else if (schema_field.getType ().isInterface ()) {
181+ GetAnnotationInt32 (schema_field.getType ().asInterface ().getProto (),
182+ COUNT_ANNOTATION_ID, &count);
183+ }
184+ }
185+
186+
187+ if (inserted.second && !field.retval && !field.exception .size ()) {
188+ field.args = count;
189+ }
190+ }
191+
192+ void mergeFields ()
193+ {
194+ for (auto & field : field_idx) {
195+ auto has_field = field_idx.find (" has" + Cap (field.first ));
196+ if (has_field != field_idx.end ()) {
197+ fields[has_field->second ].skip = true ;
198+ fields[field.second ].optional = true ;
199+ }
200+ auto want_field = field_idx.find (" want" + Cap (field.first ));
201+ if (want_field != field_idx.end () && fields[want_field->second ].param_is_set ) {
202+ fields[want_field->second ].skip = true ;
203+ fields[field.second ].requested = true ;
204+ }
205+ }
206+ }
207+ };
208+
128209// src_file is path to .capnp file to generate stub code from.
129210//
130211// src_prefix can be used to generate outputs in a different directory than the
@@ -430,85 +511,14 @@ static void Generate(kj::StringPtr src_prefix,
430511 const bool is_construct = method_name == kj::StringPtr{" construct" };
431512 const bool is_destroy = method_name == kj::StringPtr{" destroy" };
432513
433- struct Field
434- {
435- ::capnp::StructSchema::Field param;
436- bool param_is_set = false ;
437- ::capnp::StructSchema::Field result;
438- bool result_is_set = false ;
439- int args = 0 ;
440- bool retval = false ;
441- bool optional = false ;
442- bool requested = false ;
443- bool skip = false ;
444- kj::StringPtr exception;
445- };
446-
447- std::vector<Field> fields;
448- std::map<kj::StringPtr, int > field_idx; // name -> args index
449- bool has_result = false ;
450-
451- auto add_field = [&](const ::capnp::StructSchema::Field& schema_field, bool param) {
452- if (AnnotationExists (schema_field.getProto (), SKIP_ANNOTATION_ID)) {
453- return ;
454- }
455-
456- auto field_name = schema_field.getProto ().getName ();
457- auto inserted = field_idx.emplace (field_name, fields.size ());
458- if (inserted.second ) {
459- fields.emplace_back ();
460- }
461- auto & field = fields[inserted.first ->second ];
462- if (param) {
463- field.param = schema_field;
464- field.param_is_set = true ;
465- } else {
466- field.result = schema_field;
467- field.result_is_set = true ;
468- }
469-
470- if (!param && field_name == kj::StringPtr{" result" }) {
471- field.retval = true ;
472- has_result = true ;
473- }
474-
475- GetAnnotationText (schema_field.getProto (), EXCEPTION_ANNOTATION_ID, &field.exception );
476-
477- int32_t count = 1 ;
478- if (!GetAnnotationInt32 (schema_field.getProto (), COUNT_ANNOTATION_ID, &count)) {
479- if (schema_field.getType ().isStruct ()) {
480- GetAnnotationInt32 (schema_field.getType ().asStruct ().getProto (),
481- COUNT_ANNOTATION_ID, &count);
482- } else if (schema_field.getType ().isInterface ()) {
483- GetAnnotationInt32 (schema_field.getType ().asInterface ().getProto (),
484- COUNT_ANNOTATION_ID, &count);
485- }
486- }
487-
488-
489- if (inserted.second && !field.retval && !field.exception .size ()) {
490- field.args = count;
491- }
492- };
493-
514+ FieldList fields;
494515 for (const auto schema_field : method.getParamType ().getFields ()) {
495- add_field (schema_field, true );
516+ fields. addField (schema_field, true );
496517 }
497518 for (const auto schema_field : method.getResultType ().getFields ()) {
498- add_field (schema_field, false );
499- }
500- for (auto & field : field_idx) {
501- auto has_field = field_idx.find (" has" + Cap (field.first ));
502- if (has_field != field_idx.end ()) {
503- fields[has_field->second ].skip = true ;
504- fields[field.second ].optional = true ;
505- }
506- auto want_field = field_idx.find (" want" + Cap (field.first ));
507- if (want_field != field_idx.end () && fields[want_field->second ].param_is_set ) {
508- fields[want_field->second ].skip = true ;
509- fields[field.second ].requested = true ;
510- }
519+ fields.addField (schema_field, false );
511520 }
521+ fields.mergeFields ();
512522
513523 if (!is_construct && !is_destroy && (&method_interface == &interface)) {
514524 methods << " template<>\n " ;
@@ -524,7 +534,7 @@ static void Generate(kj::StringPtr src_prefix,
524534 std::ostringstream server_invoke_start;
525535 std::ostringstream server_invoke_end;
526536 int argc = 0 ;
527- for (const auto & field : fields) {
537+ for (const auto & field : fields. fields ) {
528538 if (field.skip ) continue ;
529539
530540 const auto & f = field.param_is_set ? field.param : field.result ;
@@ -603,12 +613,12 @@ static void Generate(kj::StringPtr src_prefix,
603613 def_client << " ProxyClient<" << message_namespace << " ::" << node_name << " >::M" << method_ordinal
604614 << " ::Result ProxyClient<" << message_namespace << " ::" << node_name << " >::" << method_name
605615 << " (" << super_str << client_args.str () << " ) {\n " ;
606- if (has_result) {
616+ if (fields. has_result ) {
607617 def_client << " typename M" << method_ordinal << " ::Result result;\n " ;
608618 }
609619 def_client << " clientInvoke(" << self_str << " , &" << message_namespace << " ::" << node_name
610620 << " ::Client::" << method_name << " Request" << client_invoke.str () << " );\n " ;
611- if (has_result) def_client << " return result;\n " ;
621+ if (fields. has_result ) def_client << " return result;\n " ;
612622 def_client << " }\n " ;
613623
614624 server << " kj::Promise<void> " << method_name << " (" << Cap (method_name)
0 commit comments