Skip to content

Commit 5a52ea0

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 3a69d47 commit 5a52ea0

File tree

1 file changed

+88
-78
lines changed

1 file changed

+88
-78
lines changed

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
@@ -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

Comments
 (0)