Skip to content

Commit db716bb

Browse files
committed
mpgen refactor: Move field handling code to FieldList class
This is a move-only change that should be easy to review with --color-moved. No behavior is changing.
1 parent 8a5e3ae commit db716bb

1 file changed

Lines changed: 88 additions & 78 deletions

File tree

src/mp/gen.cpp

Lines changed: 88 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)