9#include <capnp/schema.h>
10#include <capnp/schema-parser.h>
17#include <initializer_list>
21#include <kj/filesystem.h>
29#include <system_error>
34#define PROXY_BIN "mpgen"
35#define PROXY_DECL "mp/proxy.h"
36#define PROXY_TYPES "mp/proxy-types.h"
47template <
typename Reader>
50 for (
const auto annotation : reader.getAnnotations()) {
51 if (annotation.getId() ==
id) {
58template <
typename Reader>
61 for (
const auto annotation : reader.getAnnotations()) {
62 if (annotation.getId() ==
id) {
63 *result = annotation.getValue().getText();
70template <
typename Reader>
73 for (
const auto annotation : reader.getAnnotations()) {
74 if (annotation.getId() ==
id) {
75 *result = annotation.getValue().getInt32();
82static void ForEachMethod(
const capnp::InterfaceSchema& interface,
const std::function<
void(
const capnp::InterfaceSchema& interface,
const capnp::InterfaceSchema::Method)>& callback)
84 for (
const auto super : interface.getSuperclasses()) {
87 for (
const auto method : interface.getMethods()) {
88 callback(interface, method);
95template <class OutputStream, class Array, const char* Enable = decltype(std::declval<Array>().begin())()>
96static OutputStream&
operator<<(OutputStream& os,
const Array& array)
98 os.write(array.begin(), array.size());
104 template <
typename Value>
110 operator std::string()
const {
return m_os.str(); }
114static std::string
Cap(kj::StringPtr str)
116 std::string result = str;
117 if (!result.empty() &&
'a' <= result[0] && result[0] <=
'z') result[0] -=
'a' -
'A';
123 return !(type.isVoid() || type.isBool() || type.isInt8() || type.isInt16() || type.isInt32() || type.isInt64() ||
124 type.isUInt8() || type.isUInt16() || type.isUInt32() || type.isUInt64() || type.isFloat32() ||
125 type.isFloat64() || type.isEnum());
142 kj::StringPtr include_prefix,
143 kj::StringPtr src_file,
144 const std::vector<kj::StringPtr>& import_paths,
145 const kj::ReadableDirectory& src_dir,
146 const std::vector<kj::Own<const kj::ReadableDirectory>>& import_dirs)
148 std::string output_path;
149 if (src_prefix == kj::StringPtr{
"."}) {
150 output_path = src_file;
151 }
else if (!src_file.startsWith(src_prefix) || src_file.size() <= src_prefix.size() ||
152 src_file[src_prefix.size()] !=
'/') {
153 throw std::runtime_error(
"src_prefix is not src_file prefix");
155 output_path = src_file.slice(src_prefix.size() + 1);
158 std::string include_path;
159 if (include_prefix == kj::StringPtr{
"."}) {
160 include_path = src_file;
161 }
else if (!src_file.startsWith(include_prefix) || src_file.size() <= include_prefix.size() ||
162 src_file[include_prefix.size()] !=
'/') {
163 throw std::runtime_error(
"include_prefix is not src_file prefix");
165 include_path = src_file.slice(include_prefix.size() + 1);
168 std::string include_base = include_path;
169 const std::string::size_type p = include_base.rfind(
'.');
170 if (p != std::string::npos) include_base.erase(p);
172 std::vector<std::string>
args;
173 args.emplace_back(capnp_PREFIX
"/bin/capnp");
174 args.emplace_back(
"compile");
175 args.emplace_back(
"--src-prefix=");
176 args.back().append(src_prefix.cStr(), src_prefix.size());
177 for (
const auto& import_path : import_paths) {
178 args.emplace_back(
"--import-path=");
179 args.back().append(import_path.cStr(), import_path.size());
181 args.emplace_back(
"--output=" capnp_PREFIX
"/bin/capnpc-c++");
182 args.emplace_back(src_file);
183 const int pid = fork();
185 throw std::system_error(errno, std::system_category(),
"fork");
192 throw std::runtime_error(
"Invoking " capnp_PREFIX
"/bin/capnp failed");
195 const capnp::SchemaParser parser;
196 auto directory_pointers = kj::heapArray<const kj::ReadableDirectory*>(import_dirs.size());
197 for (
size_t i = 0; i < import_dirs.size(); ++i) {
198 directory_pointers[i] = import_dirs[i].get();
200 auto file_schema = parser.parseFromDirectory(src_dir, kj::Path::parse(output_path), directory_pointers);
202 std::ofstream cpp_server(output_path +
".proxy-server.c++");
203 cpp_server <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
204 cpp_server <<
"// IWYU pragma: no_include <kj/memory.h>\n";
205 cpp_server <<
"// IWYU pragma: no_include <memory>\n";
206 cpp_server <<
"// IWYU pragma: begin_keep\n";
207 cpp_server <<
"#include <" << include_path <<
".proxy.h>\n";
208 cpp_server <<
"#include <" << include_path <<
".proxy-types.h>\n";
209 cpp_server <<
"#include <capnp/generated-header-support.h>\n";
210 cpp_server <<
"#include <cstring>\n";
211 cpp_server <<
"#include <kj/async.h>\n";
212 cpp_server <<
"#include <kj/common.h>\n";
213 cpp_server <<
"#include <kj/exception.h>\n";
214 cpp_server <<
"#include <kj/tuple.h>\n";
215 cpp_server <<
"#include <mp/proxy.h>\n";
216 cpp_server <<
"#include <mp/util.h>\n";
217 cpp_server <<
"#include <" <<
PROXY_TYPES <<
">\n";
218 cpp_server <<
"// IWYU pragma: end_keep\n\n";
219 cpp_server <<
"namespace mp {\n";
221 std::ofstream cpp_client(output_path +
".proxy-client.c++");
222 cpp_client <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
223 cpp_client <<
"// IWYU pragma: no_include <kj/memory.h>\n";
224 cpp_client <<
"// IWYU pragma: no_include <memory>\n";
225 cpp_client <<
"// IWYU pragma: begin_keep\n";
226 cpp_client <<
"#include <" << include_path <<
".h>\n";
227 cpp_client <<
"#include <" << include_path <<
".proxy.h>\n";
228 cpp_client <<
"#include <" << include_path <<
".proxy-types.h>\n";
229 cpp_client <<
"#include <capnp/generated-header-support.h>\n";
230 cpp_client <<
"#include <cstring>\n";
231 cpp_client <<
"#include <kj/common.h>\n";
232 cpp_client <<
"#include <mp/proxy.h>\n";
233 cpp_client <<
"#include <mp/util.h>\n";
234 cpp_client <<
"#include <" <<
PROXY_TYPES <<
">\n";
235 cpp_client <<
"// IWYU pragma: end_keep\n\n";
236 cpp_client <<
"namespace mp {\n";
238 std::ofstream cpp_types(output_path +
".proxy-types.c++");
239 cpp_types <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
240 cpp_types <<
"// IWYU pragma: no_include \"mp/proxy.h\"\n";
241 cpp_types <<
"// IWYU pragma: no_include \"mp/proxy-io.h\"\n";
242 cpp_types <<
"#include <" << include_path <<
".proxy.h>\n";
243 cpp_types <<
"#include <" << include_path <<
".proxy-types.h> // IWYU pragma: keep\n";
244 cpp_types <<
"#include <" <<
PROXY_TYPES <<
">\n\n";
245 cpp_types <<
"namespace mp {\n";
247 std::string guard = output_path;
248 std::ranges::transform(guard, guard.begin(), [](
unsigned char c) ->
unsigned char {
249 if (
'0' <= c && c <=
'9') return c;
250 if (
'A' <= c && c <=
'Z') return c;
251 if (
'a' <= c && c <=
'z') return c -
'a' +
'A';
255 std::ofstream inl(output_path +
".proxy-types.h");
256 inl <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
257 inl <<
"#ifndef " << guard <<
"_PROXY_TYPES_H\n";
258 inl <<
"#define " << guard <<
"_PROXY_TYPES_H\n\n";
259 inl <<
"// IWYU pragma: no_include \"mp/proxy.h\"\n";
260 inl <<
"#include <mp/proxy.h> // IWYU pragma: keep\n";
261 inl <<
"#include <" << include_path <<
".proxy.h> // IWYU pragma: keep\n";
262 for (
const auto annotation : file_schema.getProto().getAnnotations()) {
264 inl <<
"#include \"" << annotation.getValue().getText() <<
"\" // IWYU pragma: export\n";
267 inl <<
"namespace mp {\n";
269 std::ofstream h(output_path +
".proxy.h");
270 h <<
"// Generated by " PROXY_BIN " from " << src_file <<
"\n\n";
271 h <<
"#ifndef " << guard <<
"_PROXY_H\n";
272 h <<
"#define " << guard <<
"_PROXY_H\n\n";
273 h <<
"#include <" << include_path <<
".h> // IWYU pragma: keep\n";
274 for (
const auto annotation : file_schema.getProto().getAnnotations()) {
276 h <<
"#include \"" << annotation.getValue().getText() <<
"\" // IWYU pragma: export\n";
280 h <<
"#if defined(__GNUC__)\n";
281 h <<
"#pragma GCC diagnostic push\n";
282 h <<
"#if !defined(__has_warning)\n";
283 h <<
"#pragma GCC diagnostic ignored \"-Wsuggest-override\"\n";
284 h <<
"#elif __has_warning(\"-Wsuggest-override\")\n";
285 h <<
"#pragma GCC diagnostic ignored \"-Wsuggest-override\"\n";
288 h <<
"namespace mp {\n";
290 kj::StringPtr message_namespace;
293 std::string base_name = include_base;
294 const size_t output_slash = base_name.rfind(
'/');
295 if (output_slash != std::string::npos) {
296 base_name.erase(0, output_slash + 1);
299 std::ostringstream methods;
300 std::set<kj::StringPtr> accessors_done;
301 std::ostringstream accessors;
302 std::ostringstream dec;
303 std::ostringstream def_server;
304 std::ostringstream def_client;
305 std::ostringstream int_client;
306 std::ostringstream def_types;
308 auto add_accessor = [&](kj::StringPtr
name) {
309 if (!accessors_done.insert(
name).second)
return;
310 const std::string cap =
Cap(
name);
311 accessors <<
"struct " << cap <<
"\n";
313 accessors <<
" template<typename S> static auto get(S&& s) -> decltype(s.get" << cap <<
"()) { return s.get" << cap <<
"(); }\n";
314 accessors <<
" template<typename S> static bool has(S&& s) { return s.has" << cap <<
"(); }\n";
315 accessors <<
" template<typename S, typename A> static void set(S&& s, A&& a) { s.set" << cap
316 <<
"(std::forward<A>(a)); }\n";
317 accessors <<
" template<typename S, typename... A> static decltype(auto) init(S&& s, A&&... a) { return s.init"
318 << cap <<
"(std::forward<A>(a)...); }\n";
319 accessors <<
" template<typename S> static bool getWant(S&& s) { return s.getWant" << cap <<
"(); }\n";
320 accessors <<
" template<typename S> static void setWant(S&& s) { s.setWant" << cap <<
"(true); }\n";
321 accessors <<
" template<typename S> static bool getHas(S&& s) { return s.getHas" << cap <<
"(); }\n";
322 accessors <<
" template<typename S> static void setHas(S&& s) { s.setHas" << cap <<
"(true); }\n";
326 for (
const auto node_nested : file_schema.getProto().getNestedNodes()) {
327 kj::StringPtr node_name = node_nested.getName();
328 const auto&
node = file_schema.getNested(node_name);
329 kj::StringPtr proxied_class_type;
332 if (
node.getProto().isStruct()) {
333 const auto& struc =
node.asStruct();
334 std::ostringstream generic_name;
335 generic_name << node_name;
337 bool first_param =
true;
338 for (
const auto param :
node.getProto().getParameters()) {
344 generic_name <<
", ";
346 dec <<
"typename " << param.getName();
347 generic_name <<
"" << param.getName();
349 if (!first_param) generic_name <<
">";
351 dec <<
"struct ProxyStruct<" << message_namespace <<
"::" << generic_name.str() <<
">\n";
353 dec <<
" using Struct = " << message_namespace <<
"::" << generic_name.str() <<
";\n";
354 for (
const auto field : struc.getFields()) {
355 auto field_name = field.getProto().getName();
356 add_accessor(field_name);
357 dec <<
" using " <<
Cap(field_name) <<
"Accessor = Accessor<" << base_name
358 <<
"_fields::" <<
Cap(field_name) <<
", FIELD_IN | FIELD_OUT";
359 if (
BoxedType(field.getType())) dec <<
" | FIELD_BOXED";
362 dec <<
" using Accessors = std::tuple<";
364 for (
const auto field : struc.getFields()) {
369 dec <<
Cap(field.getProto().getName()) <<
"Accessor";
373 dec <<
" static constexpr size_t fields = " << i <<
";\n";
376 if (proxied_class_type.size()) {
377 inl <<
"template<>\n";
378 inl <<
"struct ProxyType<" << proxied_class_type <<
">\n";
381 inl <<
" using Struct = " << message_namespace <<
"::" << node_name <<
";\n";
383 for (
const auto field : struc.getFields()) {
387 auto field_name = field.getProto().getName();
388 auto member_name = field_name;
390 inl <<
" static decltype(auto) get(std::integral_constant<size_t, " << i <<
">) { return "
391 <<
"&" << proxied_class_type <<
"::" << member_name <<
"; }\n";
394 inl <<
" static constexpr size_t fields = " << i <<
";\n";
399 if (proxied_class_type.size() &&
node.getProto().isInterface()) {
400 const auto&
interface = node.asInterface();
402 std::ostringstream client;
403 client <<
"template<>\nstruct ProxyClient<" << message_namespace <<
"::" << node_name <<
"> final : ";
404 client <<
"public ProxyClientCustom<" << message_namespace <<
"::" << node_name <<
", "
405 << proxied_class_type <<
">\n{\n";
406 client <<
"public:\n";
407 client <<
" using ProxyClientCustom::ProxyClientCustom;\n";
408 client <<
" ~ProxyClient();\n";
410 std::ostringstream server;
411 server <<
"template<>\nstruct ProxyServer<" << message_namespace <<
"::" << node_name <<
"> : public "
412 <<
"ProxyServerCustom<" << message_namespace <<
"::" << node_name <<
", " << proxied_class_type
414 server <<
"public:\n";
415 server <<
" using ProxyServerCustom::ProxyServerCustom;\n";
416 server <<
" ~ProxyServer();\n";
418 const std::ostringstream client_construct;
419 const std::ostringstream client_destroy;
421 int method_ordinal = 0;
422 ForEachMethod(interface, [&] (
const capnp::InterfaceSchema& method_interface,
const capnp::InterfaceSchema::Method& method) {
423 const kj::StringPtr method_name = method.getProto().getName();
424 kj::StringPtr proxied_method_name = method_name;
427 const std::string method_prefix =
Format() << message_namespace <<
"::" << method_interface.getShortDisplayName()
428 <<
"::" <<
Cap(method_name);
429 const bool is_construct = method_name == kj::StringPtr{
"construct"};
430 const bool is_destroy = method_name == kj::StringPtr{
"destroy"};
434 ::capnp::StructSchema::Field param;
435 bool param_is_set =
false;
436 ::capnp::StructSchema::Field result;
437 bool result_is_set =
false;
440 bool optional =
false;
441 bool requested =
false;
443 kj::StringPtr exception;
446 std::vector<Field> fields;
447 std::map<kj::StringPtr, int> field_idx;
448 bool has_result =
false;
450 auto add_field = [&](const ::capnp::StructSchema::Field& schema_field,
bool param) {
455 auto field_name = schema_field.getProto().getName();
456 auto inserted = field_idx.emplace(field_name, fields.size());
457 if (inserted.second) {
458 fields.emplace_back();
460 auto& field = fields[inserted.first->second];
462 field.param = schema_field;
463 field.param_is_set =
true;
465 field.result = schema_field;
466 field.result_is_set =
true;
469 if (!param && field_name == kj::StringPtr{
"result"}) {
478 if (schema_field.getType().isStruct()) {
481 }
else if (schema_field.getType().isInterface()) {
488 if (inserted.second && !field.retval && !field.exception.size()) {
493 for (
const auto schema_field : method.getParamType().getFields()) {
494 add_field(schema_field,
true);
496 for (
const auto schema_field : method.getResultType().getFields()) {
497 add_field(schema_field,
false);
499 for (
auto& field : field_idx) {
500 auto has_field = field_idx.find(
"has" +
Cap(field.first));
501 if (has_field != field_idx.end()) {
502 fields[has_field->second].skip =
true;
503 fields[field.second].optional =
true;
505 auto want_field = field_idx.find(
"want" +
Cap(field.first));
506 if (want_field != field_idx.end() && fields[want_field->second].param_is_set) {
507 fields[want_field->second].skip =
true;
508 fields[field.second].requested =
true;
512 if (!is_construct && !is_destroy && (&method_interface == &interface)) {
513 methods <<
"template<>\n";
514 methods <<
"struct ProxyMethod<" << method_prefix <<
"Params>\n";
516 methods <<
" static constexpr auto impl = &" << proxied_class_type
517 <<
"::" << proxied_method_name <<
";\n";
521 std::ostringstream client_args;
522 std::ostringstream client_invoke;
523 std::ostringstream server_invoke_start;
524 std::ostringstream server_invoke_end;
526 for (
const auto& field : fields) {
527 if (field.skip)
continue;
529 const auto& f = field.param_is_set ? field.param : field.result;
530 auto field_name = f.getProto().getName();
531 auto field_type = f.getType();
533 std::ostringstream field_flags;
534 if (!field.param_is_set) {
535 field_flags <<
"FIELD_OUT";
536 }
else if (field.result_is_set) {
537 field_flags <<
"FIELD_IN | FIELD_OUT";
539 field_flags <<
"FIELD_IN";
541 if (field.optional) field_flags <<
" | FIELD_OPTIONAL";
542 if (field.requested) field_flags <<
" | FIELD_REQUESTED";
543 if (
BoxedType(field_type)) field_flags <<
" | FIELD_BOXED";
545 add_accessor(field_name);
547 std::ostringstream fwd_args;
548 for (
int i = 0; i < field.args; ++i) {
549 if (argc > 0) client_args <<
",";
552 client_args <<
"M" << method_ordinal <<
"::Param<" << argc <<
"> " << field_name;
553 if (field.args > 1) client_args << i;
556 if (i > 0) fwd_args <<
", ";
557 fwd_args <<
"M" << method_ordinal <<
"::Fwd<" << argc <<
">(" << field_name;
558 if (field.args > 1) fwd_args << i;
563 client_invoke <<
", ";
565 if (field.exception.size()) {
566 client_invoke <<
"ClientException<" << field.exception <<
", ";
568 client_invoke <<
"MakeClientParam<";
571 client_invoke <<
"Accessor<" << base_name <<
"_fields::" <<
Cap(field_name) <<
", "
572 << field_flags.str() <<
">>(";
575 client_invoke << field_name;
577 client_invoke << fwd_args.str();
579 client_invoke <<
")";
581 if (field.exception.size()) {
582 server_invoke_start <<
"Make<ServerExcept, " << field.exception;
583 }
else if (field.retval) {
584 server_invoke_start <<
"Make<ServerRet";
586 server_invoke_start <<
"MakeServerField<" << field.args;
588 server_invoke_start <<
", Accessor<" << base_name <<
"_fields::" <<
Cap(field_name) <<
", "
589 << field_flags.str() <<
">>(";
590 server_invoke_end <<
")";
593 const std::string static_str{is_construct || is_destroy ?
"static " :
""};
594 const std::string super_str{is_construct || is_destroy ?
"Super& super" :
""};
595 const std::string self_str{is_construct || is_destroy ?
"super" :
"*this"};
597 client <<
" using M" << method_ordinal <<
" = ProxyClientMethodTraits<" << method_prefix
599 client <<
" " << static_str <<
"typename M" << method_ordinal <<
"::Result " << method_name <<
"("
600 << super_str << client_args.str() <<
")";
602 def_client <<
"ProxyClient<" << message_namespace <<
"::" << node_name <<
">::M" << method_ordinal
603 <<
"::Result ProxyClient<" << message_namespace <<
"::" << node_name <<
">::" << method_name
604 <<
"(" << super_str << client_args.str() <<
") {\n";
606 def_client <<
" typename M" << method_ordinal <<
"::Result result;\n";
608 def_client <<
" clientInvoke(" << self_str <<
", &" << message_namespace <<
"::" << node_name
609 <<
"::Client::" << method_name <<
"Request" << client_invoke.str() <<
");\n";
610 if (has_result) def_client <<
" return result;\n";
613 server <<
" kj::Promise<void> " << method_name <<
"(" <<
Cap(method_name)
614 <<
"Context call_context) override;\n";
616 def_server <<
"kj::Promise<void> ProxyServer<" << message_namespace <<
"::" << node_name
617 <<
">::" << method_name <<
"(" <<
Cap(method_name)
618 <<
"Context call_context) {\n"
619 " return serverInvoke(*this, call_context, "
620 << server_invoke_start.str();
622 def_server <<
"ServerDestroy()";
624 def_server <<
"ServerCall()";
626 def_server << server_invoke_end.str() <<
");\n}\n";
632 dec <<
"\n" << client.str() <<
"\n" << server.str() <<
"\n";
633 KJ_IF_MAYBE(bracket, proxied_class_type.findFirst(
'<')) {
638 dec <<
"template<>\nstruct ProxyType<" << proxied_class_type <<
">\n{\n";
639 dec <<
" using Type = " << proxied_class_type <<
";\n";
640 dec <<
" using Message = " << message_namespace <<
"::" << node_name <<
";\n";
641 dec <<
" using Client = ProxyClient<Message>;\n";
642 dec <<
" using Server = ProxyServer<Message>;\n";
644 int_client <<
"ProxyTypeRegister t" << node_nested.getId() <<
"{TypeList<" << proxied_class_type <<
">{}};\n";
646 def_types <<
"ProxyClient<" << message_namespace <<
"::" << node_name
647 <<
">::~ProxyClient() { clientDestroy(*this); " << client_destroy.str() <<
" }\n";
648 def_types <<
"ProxyServer<" << message_namespace <<
"::" << node_name
649 <<
">::~ProxyServer() { serverDestroy(*this); }\n";
653 h << methods.str() <<
"namespace " << base_name <<
"_fields {\n"
654 << accessors.str() <<
"} // namespace " << base_name <<
"_fields\n"
657 cpp_server << def_server.str();
658 cpp_server <<
"} // namespace mp\n";
660 cpp_client << def_client.str();
661 cpp_client <<
"namespace {\n" << int_client.str() <<
"} // namespace\n";
662 cpp_client <<
"} // namespace mp\n";
664 cpp_types << def_types.str();
665 cpp_types <<
"} // namespace mp\n";
667 inl <<
"} // namespace mp\n";
670 h <<
"} // namespace mp\n";
671 h <<
"#if defined(__GNUC__)\n";
672 h <<
"#pragma GCC diagnostic pop\n";
680 std::cerr <<
"Usage: " <<
PROXY_BIN <<
" SRC_PREFIX INCLUDE_PREFIX SRC_FILE [IMPORT_PATH...]\n";
683 std::vector<kj::StringPtr> import_paths;
684 std::vector<kj::Own<const kj::ReadableDirectory>> import_dirs;
685 auto fs = kj::newDiskFilesystem();
686 auto cwd = fs->getCurrentPath();
687 kj::Own<const kj::ReadableDirectory> src_dir;
688 KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(argv[1]))) {
689 src_dir = kj::mv(*dir);
691 throw std::runtime_error(std::string(
"Failed to open src_prefix prefix directory: ") + argv[1]);
693 for (
int i = 4; i < argc; ++i) {
694 KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(argv[i]))) {
695 import_paths.emplace_back(argv[i]);
696 import_dirs.emplace_back(kj::mv(*dir));
698 throw std::runtime_error(std::string(
"Failed to open import directory: ") + argv[i]);
701 for (
const char* path : {CMAKE_INSTALL_PREFIX
"/include", capnp_PREFIX
"/include"}) {
702 KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(path))) {
703 import_paths.emplace_back(path);
704 import_dirs.emplace_back(kj::mv(*dir));
708 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)
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
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.