@@ -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
@@ -428,85 +509,14 @@ static void Generate(kj::StringPtr src_prefix,
428509 const bool is_construct = method_name == kj::StringPtr{" construct" };
429510 const bool is_destroy = method_name == kj::StringPtr{" destroy" };
430511
431- struct Field
432- {
433- ::capnp::StructSchema::Field param;
434- bool param_is_set = false ;
435- ::capnp::StructSchema::Field result;
436- bool result_is_set = false ;
437- int args = 0 ;
438- bool retval = false ;
439- bool optional = false ;
440- bool requested = false ;
441- bool skip = false ;
442- kj::StringPtr exception;
443- };
444-
445- std::vector<Field> fields;
446- std::map<kj::StringPtr, int > field_idx; // name -> args index
447- bool has_result = false ;
448-
449- auto add_field = [&](const ::capnp::StructSchema::Field& schema_field, bool param) {
450- if (AnnotationExists (schema_field.getProto (), SKIP_ANNOTATION_ID)) {
451- return ;
452- }
453-
454- auto field_name = schema_field.getProto ().getName ();
455- auto inserted = field_idx.emplace (field_name, fields.size ());
456- if (inserted.second ) {
457- fields.emplace_back ();
458- }
459- auto & field = fields[inserted.first ->second ];
460- if (param) {
461- field.param = schema_field;
462- field.param_is_set = true ;
463- } else {
464- field.result = schema_field;
465- field.result_is_set = true ;
466- }
467-
468- if (!param && field_name == kj::StringPtr{" result" }) {
469- field.retval = true ;
470- has_result = true ;
471- }
472-
473- GetAnnotationText (schema_field.getProto (), EXCEPTION_ANNOTATION_ID, &field.exception );
474-
475- int32_t count = 1 ;
476- if (!GetAnnotationInt32 (schema_field.getProto (), COUNT_ANNOTATION_ID, &count)) {
477- if (schema_field.getType ().isStruct ()) {
478- GetAnnotationInt32 (schema_field.getType ().asStruct ().getProto (),
479- COUNT_ANNOTATION_ID, &count);
480- } else if (schema_field.getType ().isInterface ()) {
481- GetAnnotationInt32 (schema_field.getType ().asInterface ().getProto (),
482- COUNT_ANNOTATION_ID, &count);
483- }
484- }
485-
486-
487- if (inserted.second && !field.retval && !field.exception .size ()) {
488- field.args = count;
489- }
490- };
491-
512+ FieldList fields;
492513 for (const auto schema_field : method.getParamType ().getFields ()) {
493- add_field (schema_field, true );
514+ fields. addField (schema_field, true );
494515 }
495516 for (const auto schema_field : method.getResultType ().getFields ()) {
496- add_field (schema_field, false );
497- }
498- for (auto & field : field_idx) {
499- auto has_field = field_idx.find (" has" + Cap (field.first ));
500- if (has_field != field_idx.end ()) {
501- fields[has_field->second ].skip = true ;
502- fields[field.second ].optional = true ;
503- }
504- auto want_field = field_idx.find (" want" + Cap (field.first ));
505- if (want_field != field_idx.end () && fields[want_field->second ].param_is_set ) {
506- fields[want_field->second ].skip = true ;
507- fields[field.second ].requested = true ;
508- }
517+ fields.addField (schema_field, false );
509518 }
519+ fields.mergeFields ();
510520
511521 if (!is_construct && !is_destroy && (&method_interface == &interface)) {
512522 methods << " template<>\n " ;
@@ -522,7 +532,7 @@ static void Generate(kj::StringPtr src_prefix,
522532 std::ostringstream server_invoke_start;
523533 std::ostringstream server_invoke_end;
524534 int argc = 0 ;
525- for (const auto & field : fields) {
535+ for (const auto & field : fields. fields ) {
526536 if (field.skip ) continue ;
527537
528538 const auto & f = field.param_is_set ? field.param : field.result ;
@@ -601,12 +611,12 @@ static void Generate(kj::StringPtr src_prefix,
601611 def_client << " ProxyClient<" << message_namespace << " ::" << node_name << " >::M" << method_ordinal
602612 << " ::Result ProxyClient<" << message_namespace << " ::" << node_name << " >::" << method_name
603613 << " (" << super_str << client_args.str () << " ) {\n " ;
604- if (has_result) {
614+ if (fields. has_result ) {
605615 def_client << " typename M" << method_ordinal << " ::Result result;\n " ;
606616 }
607617 def_client << " clientInvoke(" << self_str << " , &" << message_namespace << " ::" << node_name
608618 << " ::Client::" << method_name << " Request" << client_invoke.str () << " );\n " ;
609- if (has_result) def_client << " return result;\n " ;
619+ if (fields. has_result ) def_client << " return result;\n " ;
610620 def_client << " }\n " ;
611621
612622 server << " kj::Promise<void> " << method_name << " (" << Cap (method_name)
0 commit comments