9#include <capnp/schema.capnp.h>
10#include <capnp/schema.h>
11#include <capnp/schema-parser.h>
18#include <initializer_list>
22#include <kj/filesystem.h>
30#include <system_error>
35#define PROXY_BIN "mpgen"
36#define PROXY_DECL "mp/proxy.h"
37#define PROXY_TYPES "mp/proxy-types.h"
48template <
typename Reader>
51 for (
const auto annotation :
reader.getAnnotations()) {
52 if (annotation.getId() ==
id) {
59template <
typename Reader>
62 for (
const auto annotation :
reader.getAnnotations()) {
63 if (annotation.getId() ==
id) {
64 *result = annotation.getValue().getText();
71template <
typename Reader>
74 for (
const auto annotation :
reader.getAnnotations()) {
75 if (annotation.getId() ==
id) {
76 *result = annotation.getValue().getInt32();
83static void ForEachMethod(
const capnp::InterfaceSchema& interface,
const std::function<
void(
const capnp::InterfaceSchema& interface,
const capnp::InterfaceSchema::Method)>& callback)
85 for (
const auto super : interface.getSuperclasses()) {
88 for (
const auto method : interface.getMethods()) {
89 callback(interface, method);
96template <class OutputStream, class Array, const char* Enable = decltype(std::declval<Array>().begin())()>
97static OutputStream&
operator<<(OutputStream& os,
const Array& array)
99 os.write(array.begin(), array.size());
105 template <
typename Value>
111 operator std::string()
const {
return m_os.str(); }
115static std::string
Cap(kj::StringPtr str)
117 std::string result = str;
118 if (!result.empty() &&
'a' <= result[0] && result[0] <=
'z') result[0] -=
'a' -
'A';
124 return !(type.isVoid() || type.isBool() || type.isInt8() || type.isInt16() || type.isInt32() || type.isInt64() ||
125 type.isUInt8() || type.isUInt16() || type.isUInt32() || type.isUInt64() || type.isFloat32() ||
126 type.isFloat64() || type.isEnum());
149 void addField(const ::capnp::StructSchema::Field& schema_field,
bool param,
bool result)
151 auto field_name = schema_field.getProto().getName();
153 if (inserted.second) {
156 auto& field =
fields[inserted.first->second];
158 field.param = schema_field;
159 field.param_is_set =
true;
162 field.result = schema_field;
163 field.result_is_set =
true;
166 if (!param && field_name == kj::StringPtr{
"result"}) {
178 if (schema_field.getType().isStruct()) {
181 }
else if (schema_field.getType().isInterface()) {
188 if (inserted.second && !field.retval && !field.exception.size()) {
196 auto has_field =
field_idx.find(
"has" +
Cap(field.first));
198 fields[has_field->second].skip =
true;
199 fields[field.second].optional =
true;
201 auto want_field =
field_idx.find(
"want" +
Cap(field.first));
202 if (want_field !=
field_idx.end() &&
fields[want_field->second].param_is_set) {
203 fields[want_field->second].skip =
true;
204 fields[field.second].requested =
true;
213 const auto field_name = f.getProto().getName();
214 const auto field_type = f.getType();
216 std::ostringstream
out;
217 out <<
"Accessor<" << base_name <<
"_fields::" <<
Cap(field_name) <<
", ";
221 out <<
"FIELD_IN | FIELD_OUT";
246 kj::StringPtr include_prefix,
247 kj::StringPtr src_file,
248 const std::vector<kj::StringPtr>& import_paths,
249 const kj::ReadableDirectory& src_dir,
250 const std::vector<kj::Own<const kj::ReadableDirectory>>& import_dirs)
252 std::string output_path;
253 if (src_prefix == kj::StringPtr{
"."}) {
254 output_path = src_file;
255 }
else if (!src_file.startsWith(src_prefix) || src_file.size() <= src_prefix.size() ||
256 src_file[src_prefix.size()] !=
'/') {
257 throw std::runtime_error(
"src_prefix is not src_file prefix");
259 output_path = src_file.slice(src_prefix.size() + 1);
262 std::string include_path;
263 if (include_prefix == kj::StringPtr{
"."}) {
264 include_path = src_file;
265 }
else if (!src_file.startsWith(include_prefix) || src_file.size() <= include_prefix.size() ||
266 src_file[include_prefix.size()] !=
'/') {
267 throw std::runtime_error(
"include_prefix is not src_file prefix");
269 include_path = src_file.slice(include_prefix.size() + 1);
272 std::string include_base = include_path;
273 const std::string::size_type p = include_base.rfind(
'.');
274 if (p != std::string::npos) include_base.erase(p);
276 std::vector<std::string>
args;
277 args.emplace_back(capnp_PREFIX
"/bin/capnp");
278 args.emplace_back(
"compile");
279 args.emplace_back(
"--src-prefix=");
280 args.back().append(src_prefix.cStr(), src_prefix.size());
281 for (
const auto& import_path : import_paths) {
282 args.emplace_back(
"--import-path=");
283 args.back().append(import_path.cStr(), import_path.size());
285 args.emplace_back(
"--output=" capnp_PREFIX
"/bin/capnpc-c++");
286 args.emplace_back(src_file);
287 const int pid = fork();
289 throw std::system_error(errno, std::system_category(),
"fork");
296 throw std::runtime_error(
"Invoking " capnp_PREFIX
"/bin/capnp failed");
299 const capnp::SchemaParser parser;
300 auto directory_pointers = kj::heapArray<const kj::ReadableDirectory*>(import_dirs.size());
301 for (
size_t i = 0; i < import_dirs.size(); ++i) {
302 directory_pointers[i] = import_dirs[i].get();
304 auto file_schema = parser.parseFromDirectory(src_dir, kj::Path::parse(output_path), directory_pointers);
306 std::ofstream cpp_server(output_path +
".proxy-server.c++");
307 cpp_server <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
308 cpp_server <<
"// IWYU pragma: no_include <kj/memory.h>\n";
309 cpp_server <<
"// IWYU pragma: no_include <memory>\n";
310 cpp_server <<
"// IWYU pragma: begin_keep\n";
311 cpp_server <<
"#include <" << include_path <<
".proxy.h>\n";
312 cpp_server <<
"#include <" << include_path <<
".proxy-types.h>\n";
313 cpp_server <<
"#include <capnp/generated-header-support.h>\n";
314 cpp_server <<
"#include <cstring>\n";
315 cpp_server <<
"#include <kj/async.h>\n";
316 cpp_server <<
"#include <kj/common.h>\n";
317 cpp_server <<
"#include <kj/exception.h>\n";
318 cpp_server <<
"#include <kj/tuple.h>\n";
319 cpp_server <<
"#include <mp/proxy.h>\n";
320 cpp_server <<
"#include <mp/util.h>\n";
321 cpp_server <<
"#include <" <<
PROXY_TYPES <<
">\n";
322 cpp_server <<
"// IWYU pragma: end_keep\n\n";
323 cpp_server <<
"namespace mp {\n";
325 std::ofstream cpp_client(output_path +
".proxy-client.c++");
326 cpp_client <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
327 cpp_client <<
"// IWYU pragma: no_include <kj/memory.h>\n";
328 cpp_client <<
"// IWYU pragma: no_include <memory>\n";
329 cpp_client <<
"// IWYU pragma: begin_keep\n";
330 cpp_client <<
"#include <" << include_path <<
".h>\n";
331 cpp_client <<
"#include <" << include_path <<
".proxy.h>\n";
332 cpp_client <<
"#include <" << include_path <<
".proxy-types.h>\n";
333 cpp_client <<
"#include <capnp/capability.h>\n";
334 cpp_client <<
"#include <capnp/common.h>\n";
335 cpp_client <<
"#include <capnp/generated-header-support.h>\n";
336 cpp_client <<
"#include <cstring>\n";
337 cpp_client <<
"#include <functional>\n";
338 cpp_client <<
"#include <kj/common.h>\n";
339 cpp_client <<
"#include <map>\n";
340 cpp_client <<
"#include <mp/proxy.h>\n";
341 cpp_client <<
"#include <mp/util.h>\n";
342 cpp_client <<
"#include <string>\n";
343 cpp_client <<
"#include <vector>\n";
344 cpp_client <<
"#include <" <<
PROXY_TYPES <<
">\n";
345 cpp_client <<
"// IWYU pragma: end_keep\n\n";
346 cpp_client <<
"namespace mp {\n";
348 std::ofstream cpp_types(output_path +
".proxy-types.c++");
349 cpp_types <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
350 cpp_types <<
"// IWYU pragma: no_include \"mp/proxy.h\"\n";
351 cpp_types <<
"// IWYU pragma: no_include \"mp/proxy-io.h\"\n";
352 cpp_types <<
"#include <" << include_path <<
".h> // IWYU pragma: keep\n";
353 cpp_types <<
"#include <" << include_path <<
".proxy.h>\n";
354 cpp_types <<
"#include <" << include_path <<
".proxy-types.h> // IWYU pragma: keep\n";
355 cpp_types <<
"#include <" <<
PROXY_TYPES <<
">\n\n";
356 cpp_types <<
"namespace mp {\n";
358 std::string guard = output_path;
359 std::ranges::transform(guard, guard.begin(), [](
unsigned char c) ->
unsigned char {
360 if (
'0' <= c && c <=
'9') return c;
361 if (
'A' <= c && c <=
'Z') return c;
362 if (
'a' <= c && c <=
'z') return c -
'a' +
'A';
366 std::ofstream inl(output_path +
".proxy-types.h");
367 inl <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
368 inl <<
"#ifndef " << guard <<
"_PROXY_TYPES_H\n";
369 inl <<
"#define " << guard <<
"_PROXY_TYPES_H\n\n";
370 inl <<
"// IWYU pragma: no_include \"mp/proxy.h\"\n";
371 inl <<
"#include <mp/proxy.h> // IWYU pragma: keep\n";
372 inl <<
"#include <" << include_path <<
".proxy.h> // IWYU pragma: keep\n";
373 for (
const auto annotation : file_schema.getProto().getAnnotations()) {
375 inl <<
"#include \"" << annotation.getValue().getText() <<
"\" // IWYU pragma: export\n";
378 inl <<
"namespace mp {\n";
380 std::ofstream h(output_path +
".proxy.h");
381 h <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
382 h <<
"#ifndef " << guard <<
"_PROXY_H\n";
383 h <<
"#define " << guard <<
"_PROXY_H\n\n";
384 h <<
"#include <" << include_path <<
".h> // IWYU pragma: keep\n";
385 for (
const auto annotation : file_schema.getProto().getAnnotations()) {
387 h <<
"#include \"" << annotation.getValue().getText() <<
"\" // IWYU pragma: export\n";
391 h <<
"#if defined(__GNUC__)\n";
392 h <<
"#pragma GCC diagnostic push\n";
393 h <<
"#if !defined(__has_warning)\n";
394 h <<
"#pragma GCC diagnostic ignored \"-Wsuggest-override\"\n";
395 h <<
"#elif __has_warning(\"-Wsuggest-override\")\n";
396 h <<
"#pragma GCC diagnostic ignored \"-Wsuggest-override\"\n";
399 h <<
"namespace mp {\n";
401 kj::StringPtr message_namespace;
404 std::string base_name = include_base;
405 const size_t output_slash = base_name.rfind(
'/');
406 if (output_slash != std::string::npos) {
407 base_name.erase(0, output_slash + 1);
410 std::ostringstream methods;
411 std::set<kj::StringPtr> accessors_done;
412 std::ostringstream accessors;
413 std::ostringstream dec;
414 std::ostringstream def_server;
415 std::ostringstream def_client;
416 std::ostringstream int_client;
417 std::ostringstream def_types;
419 auto add_accessor = [&](kj::StringPtr
name) {
420 if (!accessors_done.insert(
name).second)
return;
421 const std::string cap =
Cap(
name);
422 accessors <<
"struct " << cap <<
"\n";
424 accessors <<
" template<typename S> static auto get(S&& s) -> decltype(s.get" << cap <<
"()) { return s.get" << cap <<
"(); }\n";
425 accessors <<
" template<typename S> static bool has(S&& s) { return s.has" << cap <<
"(); }\n";
426 accessors <<
" template<typename S, typename A> static void set(S&& s, A&& a) { s.set" << cap
427 <<
"(std::forward<A>(a)); }\n";
428 accessors <<
" template<typename S, typename... A> static decltype(auto) init(S&& s, A&&... a) { return s.init"
429 << cap <<
"(std::forward<A>(a)...); }\n";
430 accessors <<
" template<typename S> static bool getWant(S&& s) { return s.getWant" << cap <<
"(); }\n";
431 accessors <<
" template<typename S> static void setWant(S&& s) { s.setWant" << cap <<
"(true); }\n";
432 accessors <<
" template<typename S> static bool getHas(S&& s) { return s.getHas" << cap <<
"(); }\n";
433 accessors <<
" template<typename S> static void setHas(S&& s) { s.setHas" << cap <<
"(true); }\n";
437 for (
const auto node_nested : file_schema.getProto().getNestedNodes()) {
438 kj::StringPtr node_name = node_nested.getName();
439 const auto&
node = file_schema.getNested(node_name);
440 kj::StringPtr proxied_class_type;
443 if (
node.getProto().isStruct()) {
444 const auto& struc =
node.asStruct();
447 for (
const auto schema_field : struc.getFields()) {
448 fields.
addField(schema_field,
true,
true);
452 std::ostringstream generic_name;
453 generic_name << node_name;
455 bool first_param =
true;
456 for (
const auto param :
node.getProto().getParameters()) {
462 generic_name <<
", ";
464 dec <<
"typename " << param.getName();
465 generic_name <<
"" << param.getName();
467 if (!first_param) generic_name <<
">";
469 dec <<
"struct ProxyStruct<" << message_namespace <<
"::" << generic_name.str() <<
">\n";
471 dec <<
" using Struct = " << message_namespace <<
"::" << generic_name.str() <<
";\n";
472 for (
const auto& field : fields.
fields) {
473 auto field_name = field.param.getProto().getName();
474 add_accessor(field_name);
475 dec <<
" using " <<
Cap(field_name) <<
"Accessor = "
478 dec <<
" using Accessors = std::tuple<";
480 for (
const auto& field : fields.
fields) {
481 if (field.skip)
continue;
483 dec <<
Cap(field.param.getProto().getName()) <<
"Accessor";
487 dec <<
" static constexpr size_t fields = " << i <<
";\n";
490 if (proxied_class_type.size()) {
491 inl <<
"template<>\n";
492 inl <<
"struct ProxyType<" << proxied_class_type <<
">\n";
495 inl <<
" using Struct = " << message_namespace <<
"::" << node_name <<
";\n";
497 for (
const auto& field : fields.
fields) {
498 if (field.skip)
continue;
499 auto field_name = field.param.getProto().getName();
500 auto member_name = field_name;
502 inl <<
" static decltype(auto) get(std::integral_constant<size_t, " << i <<
">) { return "
503 <<
"&" << proxied_class_type <<
"::" << member_name <<
"; }\n";
506 inl <<
" static constexpr size_t fields = " << i <<
";\n";
511 if (proxied_class_type.size() &&
node.getProto().isInterface()) {
512 const auto&
interface = node.asInterface();
514 std::ostringstream
client;
515 client <<
"template<>\nstruct ProxyClient<" << message_namespace <<
"::" << node_name <<
"> final : ";
516 client <<
"public ProxyClientCustom<" << message_namespace <<
"::" << node_name <<
", "
517 << proxied_class_type <<
">\n{\n";
519 client <<
" using ProxyClientCustom::ProxyClientCustom;\n";
520 client <<
" ~ProxyClient();\n";
522 std::ostringstream server;
523 server <<
"template<>\nstruct ProxyServer<" << message_namespace <<
"::" << node_name <<
"> : public "
524 <<
"ProxyServerCustom<" << message_namespace <<
"::" << node_name <<
", " << proxied_class_type
526 server <<
"public:\n";
527 server <<
" using ProxyServerCustom::ProxyServerCustom;\n";
528 server <<
" ~ProxyServer();\n";
530 const std::ostringstream client_construct;
531 const std::ostringstream client_destroy;
533 int method_ordinal = 0;
534 ForEachMethod(interface, [&] (
const capnp::InterfaceSchema& method_interface,
const capnp::InterfaceSchema::Method& method) {
535 const kj::StringPtr method_name = method.getProto().getName();
536 kj::StringPtr proxied_method_name = method_name;
539 const std::string method_prefix =
Format() << message_namespace <<
"::" << method_interface.getShortDisplayName()
540 <<
"::" <<
Cap(method_name);
541 const bool is_construct = method_name == kj::StringPtr{
"construct"};
542 const bool is_destroy = method_name == kj::StringPtr{
"destroy"};
545 for (
const auto schema_field : method.getParamType().getFields()) {
546 fields.
addField(schema_field,
true,
false);
548 for (
const auto schema_field : method.getResultType().getFields()) {
549 fields.
addField(schema_field,
false,
true);
553 if (!is_construct && !is_destroy && (&method_interface == &interface)) {
554 methods <<
"template<>\n";
555 methods <<
"struct ProxyMethod<" << method_prefix <<
"Params>\n";
557 methods <<
" static constexpr auto impl = &" << proxied_class_type
558 <<
"::" << proxied_method_name <<
";\n";
562 std::ostringstream client_args;
563 std::ostringstream client_invoke;
564 std::ostringstream server_invoke_start;
565 std::ostringstream server_invoke_end;
567 for (
const auto& field : fields.
fields) {
568 if (field.skip)
continue;
570 const auto& f = field.param_is_set ? field.param : field.result;
571 auto field_name = f.getProto().getName();
572 add_accessor(field_name);
574 std::ostringstream fwd_args;
575 for (
int i = 0; i < field.args; ++i) {
576 if (argc > 0) client_args <<
",";
579 client_args <<
"M" << method_ordinal <<
"::Param<" << argc <<
"> " << field_name;
580 if (field.args > 1) client_args << i;
583 if (i > 0) fwd_args <<
", ";
584 fwd_args <<
"M" << method_ordinal <<
"::Fwd<" << argc <<
">(" << field_name;
585 if (field.args > 1) fwd_args << i;
590 client_invoke <<
", ";
592 if (field.exception.size()) {
593 client_invoke <<
"ClientException<" << field.exception <<
", ";
595 client_invoke <<
"MakeClientParam<";
598 client_invoke <<
AccessorType(base_name, field) <<
">(";
601 client_invoke << field_name;
603 client_invoke << fwd_args.str();
605 client_invoke <<
")";
607 if (field.exception.size()) {
608 server_invoke_start <<
"Make<ServerExcept, " << field.exception;
609 }
else if (field.retval) {
610 server_invoke_start <<
"Make<ServerRet";
612 server_invoke_start <<
"MakeServerField<" << field.args;
614 server_invoke_start <<
", " <<
AccessorType(base_name, field) <<
">(";
615 server_invoke_end <<
")";
618 const std::string static_str{is_construct || is_destroy ?
"static " :
""};
619 const std::string super_str{is_construct || is_destroy ?
"Super& super" :
""};
620 const std::string self_str{is_construct || is_destroy ?
"super" :
"*this"};
622 client <<
" using M" << method_ordinal <<
" = ProxyClientMethodTraits<" << method_prefix
624 client <<
" " << static_str <<
"typename M" << method_ordinal <<
"::Result " << method_name <<
"("
625 << super_str << client_args.str() <<
")";
627 def_client <<
"ProxyClient<" << message_namespace <<
"::" << node_name <<
">::M" << method_ordinal
628 <<
"::Result ProxyClient<" << message_namespace <<
"::" << node_name <<
">::" << method_name
629 <<
"(" << super_str << client_args.str() <<
") {\n";
631 def_client <<
" typename M" << method_ordinal <<
"::Result result;\n";
633 def_client <<
" clientInvoke(" << self_str <<
", &" << message_namespace <<
"::" << node_name
634 <<
"::Client::" << method_name <<
"Request" << client_invoke.str() <<
");\n";
635 if (fields.
has_result) def_client <<
" return result;\n";
638 server <<
" kj::Promise<void> " << method_name <<
"(" <<
Cap(method_name)
639 <<
"Context call_context) override;\n";
641 def_server <<
"kj::Promise<void> ProxyServer<" << message_namespace <<
"::" << node_name
642 <<
">::" << method_name <<
"(" <<
Cap(method_name)
643 <<
"Context call_context) {\n"
644 " return serverInvoke(*this, call_context, "
645 << server_invoke_start.str();
647 def_server <<
"ServerDestroy()";
649 def_server <<
"ServerCall()";
651 def_server << server_invoke_end.str() <<
");\n}\n";
657 dec <<
"\n" <<
client.str() <<
"\n" << server.str() <<
"\n";
658 KJ_IF_MAYBE(bracket, proxied_class_type.findFirst(
'<')) {
663 dec <<
"template<>\nstruct ProxyType<" << proxied_class_type <<
">\n{\n";
664 dec <<
" using Type = " << proxied_class_type <<
";\n";
665 dec <<
" using Message = " << message_namespace <<
"::" << node_name <<
";\n";
666 dec <<
" using Client = ProxyClient<Message>;\n";
667 dec <<
" using Server = ProxyServer<Message>;\n";
669 int_client <<
"ProxyTypeRegister t" << node_nested.getId() <<
"{TypeList<" << proxied_class_type <<
">{}};\n";
671 def_types <<
"ProxyClient<" << message_namespace <<
"::" << node_name
672 <<
">::~ProxyClient() { clientDestroy(*this); " << client_destroy.str() <<
" }\n";
673 def_types <<
"ProxyServer<" << message_namespace <<
"::" << node_name
674 <<
">::~ProxyServer() { serverDestroy(*this); }\n";
678 h << methods.str() <<
"namespace " << base_name <<
"_fields {\n"
679 << accessors.str() <<
"} // namespace " << base_name <<
"_fields\n"
682 cpp_server << def_server.str();
683 cpp_server <<
"} // namespace mp\n";
685 cpp_client << def_client.str();
686 cpp_client <<
"namespace {\n" << int_client.str() <<
"} // namespace\n";
687 cpp_client <<
"} // namespace mp\n";
689 cpp_types << def_types.str();
690 cpp_types <<
"} // namespace mp\n";
692 inl <<
"} // namespace mp\n";
695 h <<
"} // namespace mp\n";
696 h <<
"#if defined(__GNUC__)\n";
697 h <<
"#pragma GCC diagnostic pop\n";
705 std::cerr <<
"Usage: " <<
PROXY_BIN <<
" SRC_PREFIX INCLUDE_PREFIX SRC_FILE [IMPORT_PATH...]\n";
708 std::vector<kj::StringPtr> import_paths;
709 std::vector<kj::Own<const kj::ReadableDirectory>> import_dirs;
710 auto fs = kj::newDiskFilesystem();
711 auto cwd = fs->getCurrentPath();
712 kj::Own<const kj::ReadableDirectory> src_dir;
713 KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(argv[1]))) {
714 src_dir = kj::mv(*dir);
716 throw std::runtime_error(std::string(
"Failed to open src_prefix prefix directory: ") + argv[1]);
718 for (
int i = 4; i < argc; ++i) {
719 KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(argv[i]))) {
720 import_paths.emplace_back(argv[i]);
721 import_dirs.emplace_back(kj::mv(*dir));
723 throw std::runtime_error(std::string(
"Failed to open import directory: ") + argv[i]);
726 for (
const char* path : {CMAKE_INSTALL_PREFIX
"/include", capnp_PREFIX
"/include"}) {
727 KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(path))) {
728 import_paths.emplace_back(path);
729 import_dirs.emplace_back(kj::mv(*dir));
733 Generate(argv[1], argv[2], argv[3], import_paths, *src_dir, import_dirs);
kj::ArrayPtr< const char > CharSlice
constexpr uint64_t EXCEPTION_ANNOTATION_ID
constexpr uint64_t NAME_ANNOTATION_ID
static OutputStream & operator<<(OutputStream &os, const Array &array)
static void ForEachMethod(const capnp::InterfaceSchema &interface, const std::function< void(const capnp::InterfaceSchema &interface, const capnp::InterfaceSchema::Method)> &callback)
constexpr uint64_t SKIP_ANNOTATION_ID
int main(int argc, char **argv)
std::string AccessorType(kj::StringPtr base_name, const Field &field)
constexpr uint64_t WRAP_ANNOTATION_ID
constexpr uint64_t INCLUDE_ANNOTATION_ID
static void Generate(kj::StringPtr src_prefix, kj::StringPtr include_prefix, kj::StringPtr src_file, const std::vector< kj::StringPtr > &import_paths, const kj::ReadableDirectory &src_dir, const std::vector< kj::Own< const kj::ReadableDirectory > > &import_dirs)
static bool GetAnnotationInt32(const Reader &reader, uint64_t id, int32_t *result)
static bool BoxedType(const ::capnp::Type &type)
constexpr uint64_t INCLUDE_TYPES_ANNOTATION_ID
constexpr uint64_t NAMESPACE_ANNOTATION_ID
static bool AnnotationExists(const Reader &reader, uint64_t id)
static std::string Cap(kj::StringPtr str)
static bool GetAnnotationText(const Reader &reader, uint64_t id, kj::StringPtr *result)
constexpr uint64_t COUNT_ANNOTATION_ID
std::unique_ptr< ProxyClient< messages::FooInterface > > client
int WaitProcess(int pid)
Wait for a process to exit and return its exit code.
void ExecProcess(const std::vector< std::string > &args)
Call execvp with vector args.
::capnp::StructSchema::Field result
::capnp::StructSchema::Field param
std::vector< Field > fields
std::map< kj::StringPtr, int > field_idx
void addField(const ::capnp::StructSchema::Field &schema_field, bool param, bool result)