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 <mp/proxy.h>\n";
 
  215    cpp_server << 
"#include <mp/util.h>\n";
 
  216    cpp_server << 
"#include <" << 
PROXY_TYPES << 
">\n";
 
  217    cpp_server << 
"// IWYU pragma: end_keep\n\n";
 
  218    cpp_server << 
"namespace mp {\n";
 
  220    std::ofstream cpp_client(output_path + 
".proxy-client.c++");
 
  221    cpp_client << 
"// Generated by " PROXY_BIN " from " << src_file << 
"\n\n";
 
  222    cpp_client << 
"// IWYU pragma: no_include <kj/memory.h>\n";
 
  223    cpp_client << 
"// IWYU pragma: no_include <memory>\n";
 
  224    cpp_client << 
"// IWYU pragma: begin_keep\n";
 
  225    cpp_client << 
"#include <" << include_path << 
".h>\n";
 
  226    cpp_client << 
"#include <" << include_path << 
".proxy.h>\n";
 
  227    cpp_client << 
"#include <" << include_path << 
".proxy-types.h>\n";
 
  228    cpp_client << 
"#include <capnp/generated-header-support.h>\n";
 
  229    cpp_client << 
"#include <cstring>\n";
 
  230    cpp_client << 
"#include <kj/common.h>\n";
 
  231    cpp_client << 
"#include <mp/proxy.h>\n";
 
  232    cpp_client << 
"#include <mp/util.h>\n";
 
  233    cpp_client << 
"#include <" << 
PROXY_TYPES << 
">\n";
 
  234    cpp_client << 
"// IWYU pragma: end_keep\n\n";
 
  235    cpp_client << 
"namespace mp {\n";
 
  237    std::ofstream cpp_types(output_path + 
".proxy-types.c++");
 
  238    cpp_types << 
"// Generated by " PROXY_BIN " from " << src_file << 
"\n\n";
 
  239    cpp_types << 
"// IWYU pragma: no_include \"mp/proxy.h\"\n";
 
  240    cpp_types << 
"// IWYU pragma: no_include \"mp/proxy-io.h\"\n";
 
  241    cpp_types << 
"#include <" << include_path << 
".proxy.h>\n";
 
  242    cpp_types << 
"#include <" << include_path << 
".proxy-types.h> // IWYU pragma: keep\n";
 
  243    cpp_types << 
"#include <" << 
PROXY_TYPES << 
">\n\n";
 
  244    cpp_types << 
"namespace mp {\n";
 
  246    std::string guard = output_path;
 
  247    std::ranges::transform(guard, guard.begin(), [](
unsigned char c) -> 
unsigned char {
 
  248        if (
'0' <= c && c <= 
'9') return c;
 
  249        if (
'A' <= c && c <= 
'Z') return c;
 
  250        if (
'a' <= c && c <= 
'z') return c - 
'a' + 
'A';
 
  254    std::ofstream inl(output_path + 
".proxy-types.h");
 
  255    inl << 
"// Generated by " PROXY_BIN " from " << src_file << 
"\n\n";
 
  256    inl << 
"#ifndef " << guard << 
"_PROXY_TYPES_H\n";
 
  257    inl << 
"#define " << guard << 
"_PROXY_TYPES_H\n\n";
 
  258    inl << 
"// IWYU pragma: no_include \"mp/proxy.h\"\n";
 
  259    inl << 
"#include <mp/proxy.h> // IWYU pragma: keep\n";
 
  260    inl << 
"#include <" << include_path << 
".proxy.h> // IWYU pragma: keep\n";
 
  261    for (
const auto annotation : file_schema.getProto().getAnnotations()) {
 
  263            inl << 
"#include \"" << annotation.getValue().getText() << 
"\" // IWYU pragma: export\n";
 
  266    inl << 
"namespace mp {\n";
 
  268    std::ofstream h(output_path + 
".proxy.h");
 
  269    h << 
"// Generated by " PROXY_BIN " from " << src_file << 
"\n\n";
 
  270    h << 
"#ifndef " << guard << 
"_PROXY_H\n";
 
  271    h << 
"#define " << guard << 
"_PROXY_H\n\n";
 
  272    h << 
"#include <" << include_path << 
".h> // IWYU pragma: keep\n";
 
  273    for (
const auto annotation : file_schema.getProto().getAnnotations()) {
 
  275            h << 
"#include \"" << annotation.getValue().getText() << 
"\" // IWYU pragma: export\n";
 
  279    h << 
"#if defined(__GNUC__)\n";
 
  280    h << 
"#pragma GCC diagnostic push\n";
 
  281    h << 
"#if !defined(__has_warning)\n";
 
  282    h << 
"#pragma GCC diagnostic ignored \"-Wsuggest-override\"\n";
 
  283    h << 
"#elif __has_warning(\"-Wsuggest-override\")\n";
 
  284    h << 
"#pragma GCC diagnostic ignored \"-Wsuggest-override\"\n";
 
  287    h << 
"namespace mp {\n";
 
  289    kj::StringPtr message_namespace;
 
  292    std::string base_name = include_base;
 
  293    const size_t output_slash = base_name.rfind(
'/');
 
  294    if (output_slash != std::string::npos) {
 
  295        base_name.erase(0, output_slash + 1);
 
  298    std::ostringstream methods;
 
  299    std::set<kj::StringPtr> accessors_done;
 
  300    std::ostringstream accessors;
 
  301    std::ostringstream dec;
 
  302    std::ostringstream def_server;
 
  303    std::ostringstream def_client;
 
  304    std::ostringstream int_client;
 
  305    std::ostringstream def_types;
 
  307    auto add_accessor = [&](kj::StringPtr 
name) {
 
  308        if (!accessors_done.insert(
name).second) 
return;
 
  309        const std::string cap = 
Cap(
name);
 
  310        accessors << 
"struct " << cap << 
"\n";
 
  312        accessors << 
"    template<typename S> static auto get(S&& s) -> decltype(s.get" << cap << 
"()) { return s.get" << cap << 
"(); }\n";
 
  313        accessors << 
"    template<typename S> static bool has(S&& s) { return s.has" << cap << 
"(); }\n";
 
  314        accessors << 
"    template<typename S, typename A> static void set(S&& s, A&& a) { s.set" << cap
 
  315                  << 
"(std::forward<A>(a)); }\n";
 
  316        accessors << 
"    template<typename S, typename... A> static decltype(auto) init(S&& s, A&&... a) { return s.init" 
  317                  << cap << 
"(std::forward<A>(a)...); }\n";
 
  318        accessors << 
"    template<typename S> static bool getWant(S&& s) { return s.getWant" << cap << 
"(); }\n";
 
  319        accessors << 
"    template<typename S> static void setWant(S&& s) { s.setWant" << cap << 
"(true); }\n";
 
  320        accessors << 
"    template<typename S> static bool getHas(S&& s) { return s.getHas" << cap << 
"(); }\n";
 
  321        accessors << 
"    template<typename S> static void setHas(S&& s) { s.setHas" << cap << 
"(true); }\n";
 
  325    for (
const auto node_nested : file_schema.getProto().getNestedNodes()) {
 
  326        kj::StringPtr node_name = node_nested.getName();
 
  327        const auto& 
node = file_schema.getNested(node_name);
 
  328        kj::StringPtr proxied_class_type;
 
  331        if (
node.getProto().isStruct()) {
 
  332            const auto& struc = 
node.asStruct();
 
  333            std::ostringstream generic_name;
 
  334            generic_name << node_name;
 
  336            bool first_param = 
true;
 
  337            for (
const auto param : 
node.getProto().getParameters()) {
 
  343                    generic_name << 
", ";
 
  345                dec << 
"typename " << param.getName();
 
  346                generic_name << 
"" << param.getName();
 
  348            if (!first_param) generic_name << 
">";
 
  350            dec << 
"struct ProxyStruct<" << message_namespace << 
"::" << generic_name.str() << 
">\n";
 
  352            dec << 
"    using Struct = " << message_namespace << 
"::" << generic_name.str() << 
";\n";
 
  353            for (
const auto field : struc.getFields()) {
 
  354                auto field_name = field.getProto().getName();
 
  355                add_accessor(field_name);
 
  356                dec << 
"    using " << 
Cap(field_name) << 
"Accessor = Accessor<" << base_name
 
  357                    << 
"_fields::" << 
Cap(field_name) << 
", FIELD_IN | FIELD_OUT";
 
  358                if (
BoxedType(field.getType())) dec << 
" | FIELD_BOXED";
 
  361            dec << 
"    using Accessors = std::tuple<";
 
  363            for (
const auto field : struc.getFields()) {
 
  368                dec << 
Cap(field.getProto().getName()) << 
"Accessor";
 
  372            dec << 
"    static constexpr size_t fields = " << i << 
";\n";
 
  375            if (proxied_class_type.size()) {
 
  376                inl << 
"template<>\n";
 
  377                inl << 
"struct ProxyType<" << proxied_class_type << 
">\n";
 
  380                inl << 
"    using Struct = " << message_namespace << 
"::" << node_name << 
";\n";
 
  382                for (
const auto field : struc.getFields()) {
 
  386                    auto field_name = field.getProto().getName();
 
  387                    auto member_name = field_name;
 
  389                    inl << 
"    static decltype(auto) get(std::integral_constant<size_t, " << i << 
">) { return " 
  390                        << 
"&" << proxied_class_type << 
"::" << member_name << 
"; }\n";
 
  393                inl << 
"    static constexpr size_t fields = " << i << 
";\n";
 
  398        if (proxied_class_type.size() && 
node.getProto().isInterface()) {
 
  399            const auto& 
interface = node.asInterface();
 
  401            std::ostringstream client;
 
  402            client << 
"template<>\nstruct ProxyClient<" << message_namespace << 
"::" << node_name << 
"> final : ";
 
  403            client << 
"public ProxyClientCustom<" << message_namespace << 
"::" << node_name << 
", " 
  404                   << proxied_class_type << 
">\n{\n";
 
  405            client << 
"public:\n";
 
  406            client << 
"    using ProxyClientCustom::ProxyClientCustom;\n";
 
  407            client << 
"    ~ProxyClient();\n";
 
  409            std::ostringstream server;
 
  410            server << 
"template<>\nstruct ProxyServer<" << message_namespace << 
"::" << node_name << 
"> : public " 
  411                   << 
"ProxyServerCustom<" << message_namespace << 
"::" << node_name << 
", " << proxied_class_type
 
  413            server << 
"public:\n";
 
  414            server << 
"    using ProxyServerCustom::ProxyServerCustom;\n";
 
  415            server << 
"    ~ProxyServer();\n";
 
  417            const std::ostringstream client_construct;
 
  418            const std::ostringstream client_destroy;
 
  420            int method_ordinal = 0;
 
  421            ForEachMethod(interface, [&] (
const capnp::InterfaceSchema& method_interface, 
const capnp::InterfaceSchema::Method& method) {
 
  422                const kj::StringPtr method_name = method.getProto().getName();
 
  423                kj::StringPtr proxied_method_name = method_name;
 
  426                const std::string method_prefix = 
Format() << message_namespace << 
"::" << method_interface.getShortDisplayName()
 
  427                                                           << 
"::" << 
Cap(method_name);
 
  428                const bool is_construct = method_name == kj::StringPtr{
"construct"};
 
  429                const bool is_destroy = method_name == kj::StringPtr{
"destroy"};
 
  433                    ::capnp::StructSchema::Field param;
 
  434                    bool param_is_set = 
false;
 
  435                    ::capnp::StructSchema::Field result;
 
  436                    bool result_is_set = 
false;
 
  439                    bool optional = 
false;
 
  440                    bool requested = 
false;
 
  442                    kj::StringPtr exception;
 
  445                std::vector<Field> fields;
 
  446                std::map<kj::StringPtr, int> field_idx; 
 
  447                bool has_result = 
false;
 
  449                auto add_field = [&](const ::capnp::StructSchema::Field& schema_field, 
bool param) {
 
  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();
 
  459                    auto& field = fields[inserted.first->second];
 
  461                        field.param = schema_field;
 
  462                        field.param_is_set = 
true;
 
  464                        field.result = schema_field;
 
  465                        field.result_is_set = 
true;
 
  468                    if (!param && field_name == kj::StringPtr{
"result"}) {
 
  477                        if (schema_field.getType().isStruct()) {
 
  480                        } 
else if (schema_field.getType().isInterface()) {
 
  487                    if (inserted.second && !field.retval && !field.exception.size()) {
 
  492                for (
const auto schema_field : method.getParamType().getFields()) {
 
  493                    add_field(schema_field, 
true);
 
  495                for (
const auto schema_field : method.getResultType().getFields()) {
 
  496                    add_field(schema_field, 
false);
 
  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;
 
  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;
 
  511                if (!is_construct && !is_destroy && (&method_interface == &interface)) {
 
  512                    methods << 
"template<>\n";
 
  513                    methods << 
"struct ProxyMethod<" << method_prefix << 
"Params>\n";
 
  515                    methods << 
"    static constexpr auto impl = &" << proxied_class_type
 
  516                            << 
"::" << proxied_method_name << 
";\n";
 
  520                std::ostringstream client_args;
 
  521                std::ostringstream client_invoke;
 
  522                std::ostringstream server_invoke_start;
 
  523                std::ostringstream server_invoke_end;
 
  525                for (
const auto& field : fields) {
 
  526                    if (field.skip) 
continue;
 
  528                    const auto& f = field.param_is_set ? field.param : field.result;
 
  529                    auto field_name = f.getProto().getName();
 
  530                    auto field_type = f.getType();
 
  532                    std::ostringstream field_flags;
 
  533                    if (!field.param_is_set) {
 
  534                        field_flags << 
"FIELD_OUT";
 
  535                    } 
else if (field.result_is_set) {
 
  536                        field_flags << 
"FIELD_IN | FIELD_OUT";
 
  538                        field_flags << 
"FIELD_IN";
 
  540                    if (field.optional) field_flags << 
" | FIELD_OPTIONAL";
 
  541                    if (field.requested) field_flags << 
" | FIELD_REQUESTED";
 
  542                    if (
BoxedType(field_type)) field_flags << 
" | FIELD_BOXED";
 
  544                    add_accessor(field_name);
 
  546                    std::ostringstream fwd_args;
 
  547                    for (
int i = 0; i < field.args; ++i) {
 
  548                        if (argc > 0) client_args << 
",";
 
  551                        client_args << 
"M" << method_ordinal << 
"::Param<" << argc << 
"> " << field_name;
 
  552                        if (field.args > 1) client_args << i;
 
  555                        if (i > 0) fwd_args << 
", ";
 
  556                        fwd_args << 
"M" << method_ordinal << 
"::Fwd<" << argc << 
">(" << field_name;
 
  557                        if (field.args > 1) fwd_args << i;
 
  562                    client_invoke << 
", ";
 
  564                    if (field.exception.size()) {
 
  565                        client_invoke << 
"ClientException<" << field.exception << 
", ";
 
  567                        client_invoke << 
"MakeClientParam<";
 
  570                    client_invoke << 
"Accessor<" << base_name << 
"_fields::" << 
Cap(field_name) << 
", " 
  571                                  << field_flags.str() << 
">>(";
 
  574                        client_invoke << field_name;
 
  576                        client_invoke << fwd_args.str();
 
  578                    client_invoke << 
")";
 
  580                    if (field.exception.size()) {
 
  581                        server_invoke_start << 
"Make<ServerExcept, " << field.exception;
 
  582                    } 
else if (field.retval) {
 
  583                        server_invoke_start << 
"Make<ServerRet";
 
  585                        server_invoke_start << 
"MakeServerField<" << field.args;
 
  587                    server_invoke_start << 
", Accessor<" << base_name << 
"_fields::" << 
Cap(field_name) << 
", " 
  588                                        << field_flags.str() << 
">>(";
 
  589                    server_invoke_end << 
")";
 
  592                const std::string static_str{is_construct || is_destroy ? 
"static " : 
""};
 
  593                const std::string super_str{is_construct || is_destroy ? 
"Super& super" : 
""};
 
  594                const std::string self_str{is_construct || is_destroy ? 
"super" : 
"*this"};
 
  596                client << 
"    using M" << method_ordinal << 
" = ProxyClientMethodTraits<" << method_prefix
 
  598                client << 
"    " << static_str << 
"typename M" << method_ordinal << 
"::Result " << method_name << 
"(" 
  599                       << super_str << client_args.str() << 
")";
 
  601                def_client << 
"ProxyClient<" << message_namespace << 
"::" << node_name << 
">::M" << method_ordinal
 
  602                           << 
"::Result ProxyClient<" << message_namespace << 
"::" << node_name << 
">::" << method_name
 
  603                           << 
"(" << super_str << client_args.str() << 
") {\n";
 
  605                    def_client << 
"    typename M" << method_ordinal << 
"::Result result;\n";
 
  607                def_client << 
"    clientInvoke(" << self_str << 
", &" << message_namespace << 
"::" << node_name
 
  608                           << 
"::Client::" << method_name << 
"Request" << client_invoke.str() << 
");\n";
 
  609                if (has_result) def_client << 
"    return result;\n";
 
  612                server << 
"    kj::Promise<void> " << method_name << 
"(" << 
Cap(method_name)
 
  613                       << 
"Context call_context) override;\n";
 
  615                def_server << 
"kj::Promise<void> ProxyServer<" << message_namespace << 
"::" << node_name
 
  616                           << 
">::" << method_name << 
"(" << 
Cap(method_name)
 
  617                           << 
"Context call_context) {\n" 
  618                              "    return serverInvoke(*this, call_context, " 
  619                           << server_invoke_start.str();
 
  621                    def_server << 
"ServerDestroy()";
 
  623                    def_server << 
"ServerCall()";
 
  625                def_server << server_invoke_end.str() << 
");\n}\n";
 
  631            dec << 
"\n" << client.str() << 
"\n" << server.str() << 
"\n";
 
  632            KJ_IF_MAYBE(bracket, proxied_class_type.findFirst(
'<')) {
 
  637              dec << 
"template<>\nstruct ProxyType<" << proxied_class_type << 
">\n{\n";
 
  638              dec << 
"    using Type = " << proxied_class_type << 
";\n";
 
  639              dec << 
"    using Message = " << message_namespace << 
"::" << node_name << 
";\n";
 
  640              dec << 
"    using Client = ProxyClient<Message>;\n";
 
  641              dec << 
"    using Server = ProxyServer<Message>;\n";
 
  643              int_client << 
"ProxyTypeRegister t" << node_nested.getId() << 
"{TypeList<" << proxied_class_type << 
">{}};\n";
 
  645            def_types << 
"ProxyClient<" << message_namespace << 
"::" << node_name
 
  646                      << 
">::~ProxyClient() { clientDestroy(*this); " << client_destroy.str() << 
" }\n";
 
  647            def_types << 
"ProxyServer<" << message_namespace << 
"::" << node_name
 
  648                      << 
">::~ProxyServer() { serverDestroy(*this); }\n";
 
  652    h << methods.str() << 
"namespace " << base_name << 
"_fields {\n" 
  653      << accessors.str() << 
"} // namespace " << base_name << 
"_fields\n" 
  656    cpp_server << def_server.str();
 
  657    cpp_server << 
"} // namespace mp\n";
 
  659    cpp_client << def_client.str();
 
  660    cpp_client << 
"namespace {\n" << int_client.str() << 
"} // namespace\n";
 
  661    cpp_client << 
"} // namespace mp\n";
 
  663    cpp_types << def_types.str();
 
  664    cpp_types << 
"} // namespace mp\n";
 
  666    inl << 
"} // namespace mp\n";
 
  669    h << 
"} // namespace mp\n";
 
  670    h << 
"#if defined(__GNUC__)\n";
 
  671    h << 
"#pragma GCC diagnostic pop\n";
 
  679        std::cerr << 
"Usage: " << 
PROXY_BIN << 
" SRC_PREFIX INCLUDE_PREFIX SRC_FILE [IMPORT_PATH...]\n";
 
  682    std::vector<kj::StringPtr> import_paths;
 
  683    std::vector<kj::Own<const kj::ReadableDirectory>> import_dirs;
 
  684    auto fs = kj::newDiskFilesystem();
 
  685    auto cwd = fs->getCurrentPath();
 
  686    kj::Own<const kj::ReadableDirectory> src_dir;
 
  687    KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(argv[1]))) {
 
  688        src_dir = kj::mv(*dir);
 
  690        throw std::runtime_error(std::string(
"Failed to open src_prefix prefix directory: ") + argv[1]);
 
  692    for (
int i = 4; i < argc; ++i) {
 
  693        KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(argv[i]))) {
 
  694            import_paths.emplace_back(argv[i]);
 
  695            import_dirs.emplace_back(kj::mv(*dir));
 
  697            throw std::runtime_error(std::string(
"Failed to open import directory: ") + argv[i]);
 
  700    for (
const char* path : {CMAKE_INSTALL_PREFIX 
"/include", capnp_PREFIX 
"/include"}) {
 
  701        KJ_IF_MAYBE(dir, fs->getRoot().tryOpenSubdir(cwd.evalNative(path))) {
 
  702            import_paths.emplace_back(path);
 
  703            import_dirs.emplace_back(kj::mv(*dir));
 
  707    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.