| // Copyright 2019 The Fuchsia Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include <fidl/fidl.test.compatibility/cpp/wire.h> | 
 | #include <fidl/fidl.test.compatibility/cpp/wire_test_base.h> | 
 | #include <fidl/fidl.test.compatibility/cpp/wire_types.h> | 
 | #include <fidl/fidl.test.imported/cpp/wire.h> | 
 | #include <fidl/fidl.test.imported/cpp/wire_types.h> | 
 | #include <lib/async-loop/cpp/loop.h> | 
 | #include <lib/async-loop/default.h> | 
 | #include <lib/fdio/directory.h> | 
 | #include <lib/fdio/fd.h> | 
 | #include <lib/fdio/fdio.h> | 
 | #include <lib/fidl/cpp/interface_request.h> | 
 | #include <lib/fidl/cpp/wire/string_view.h> | 
 | #include <lib/sys/cpp/component_context.h> | 
 | #include <lib/vfs/cpp/service.h> | 
 | #include <zircon/status.h> | 
 |  | 
 | #include <cstdlib> | 
 | #include <iostream> | 
 | #include <optional> | 
 | #include <string> | 
 |  | 
 | constexpr const char kEchoInterfaceName[] = "fidl.test.compatibility.Echo"; | 
 |  | 
 | using namespace fidl_test_compatibility; | 
 |  | 
 | class EchoClientApp { | 
 |  public: | 
 |   EchoClientApp() | 
 |       : context_(sys::ComponentContext::CreateAndServeOutgoingDirectory()), | 
 |         client_(fidl::WireSyncClient<Echo>(ConnectTo())) {} | 
 |  | 
 |   // Half the methods are testing the managed flavor; the other half are testing caller-allocate. | 
 |  | 
 |   fidl::WireResult<Echo::EchoMinimal> EchoMinimal(::fidl::StringView forward_to_server) { | 
 |     return client_->EchoMinimal(std::move(forward_to_server)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoMinimalWithError> EchoMinimalWithError( | 
 |       ::fidl::StringView forward_to_server, wire::RespondWith result_variant) { | 
 |     return client_->EchoMinimalWithError(std::move(forward_to_server), result_variant); | 
 |   } | 
 |  | 
 |   fidl::Status EchoMinimalNoRetVal(::fidl::StringView forward_to_server, | 
 |                                    fidl::WireSyncEventHandler<Echo>& event_handler) { | 
 |     auto result = client_->EchoMinimalNoRetVal(std::move(forward_to_server)); | 
 |     if (!result.ok()) { | 
 |       return result; | 
 |     } | 
 |     return client_.HandleOneEvent(event_handler); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoStruct> EchoStruct(wire::Struct value, | 
 |                                                 ::fidl::StringView forward_to_server) { | 
 |     return client_->EchoStruct(std::move(value), std::move(forward_to_server)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoNamedStruct> EchoNamedStruct( | 
 |       fidl_test_imported::wire::SimpleStruct value, ::fidl::StringView forward_to_server) { | 
 |     return client_->EchoNamedStruct(std::move(value), std::move(forward_to_server)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoNamedStructWithError> EchoNamedStructWithError( | 
 |       fidl_test_imported::wire::SimpleStruct value, uint32_t err, | 
 |       ::fidl::StringView forward_to_server, fidl_test_imported::wire::WantResponse result_variant) { | 
 |     return client_->EchoNamedStructWithError(std::move(value), err, std::move(forward_to_server), | 
 |                                              result_variant); | 
 |   } | 
 |  | 
 |   fidl::Status EchoNamedStructNoRetVal(fidl_test_imported::wire::SimpleStruct value, | 
 |                                        ::fidl::StringView forward_to_server, | 
 |                                        fidl::WireSyncEventHandler<Echo>& event_handler) { | 
 |     auto result = client_->EchoNamedStructNoRetVal(std::move(value), std::move(forward_to_server)); | 
 |     if (!result.ok()) { | 
 |       return result; | 
 |     } | 
 |     return client_.HandleOneEvent(event_handler); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoStructWithError> EchoStructWithError( | 
 |       wire::Struct value, wire::DefaultEnum err, ::fidl::StringView forward_to_server, | 
 |       wire::RespondWith result_variant) { | 
 |     return client_->EchoStructWithError(std::move(value), err, std::move(forward_to_server), | 
 |                                         result_variant); | 
 |   } | 
 |  | 
 |   fidl::Status EchoStructNoRetVal(wire::Struct value, ::fidl::StringView forward_to_server, | 
 |                                   fidl::WireSyncEventHandler<Echo>& event_handler) { | 
 |     auto result = client_->EchoStructNoRetVal(std::move(value), std::move(forward_to_server)); | 
 |     if (!result.ok()) { | 
 |       return result; | 
 |     } | 
 |     return client_.HandleOneEvent(event_handler); | 
 |   } | 
 |  | 
 |   fidl::WireUnownedResult<Echo::EchoArrays> EchoArrays(::fidl::BufferSpan buffer, | 
 |                                                        wire::ArraysStruct value, | 
 |                                                        ::fidl::StringView forward_to_server) { | 
 |     return client_.buffer(buffer)->EchoArrays(std::move(value), forward_to_server); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoArraysWithError> EchoArraysWithError( | 
 |       wire::ArraysStruct value, wire::DefaultEnum err, ::fidl::StringView forward_to_server, | 
 |       wire::RespondWith result_variant) { | 
 |     return client_->EchoArraysWithError(std::move(value), err, std::move(forward_to_server), | 
 |                                         result_variant); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoVectors> EchoVectors(wire::VectorsStruct value, | 
 |                                                   ::fidl::StringView forward_to_server) { | 
 |     return client_->EchoVectors(std::move(value), std::move(forward_to_server)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoVectorsWithError> EchoVectorsWithError( | 
 |       wire::VectorsStruct value, wire::DefaultEnum err, ::fidl::StringView forward_to_server, | 
 |       wire::RespondWith result_variant) { | 
 |     return client_->EchoVectorsWithError(std::move(value), err, std::move(forward_to_server), | 
 |                                          result_variant); | 
 |   } | 
 |  | 
 |   fidl::WireUnownedResult<Echo::EchoTable> EchoTable(::fidl::BufferSpan buffer, | 
 |                                                      wire::AllTypesTable value, | 
 |                                                      ::fidl::StringView forward_to_server) { | 
 |     return client_.buffer(buffer)->EchoTable(value, forward_to_server); | 
 |   } | 
 |  | 
 |   fidl::WireUnownedResult<Echo::EchoTableWithError> EchoTableWithError( | 
 |       ::fidl::BufferSpan buffer, wire::AllTypesTable value, wire::DefaultEnum err, | 
 |       ::fidl::StringView forward_to_server, wire::RespondWith result_variant) { | 
 |     return client_.buffer(buffer)->EchoTableWithError(value, err, forward_to_server, | 
 |                                                       result_variant); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoXunions> EchoXunions(::fidl::VectorView<wire::AllTypesXunion> value, | 
 |                                                   ::fidl::StringView forward_to_server) { | 
 |     return client_->EchoXunions(std::move(value), std::move(forward_to_server)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoXunionsWithError> EchoXunionsWithError( | 
 |       ::fidl::VectorView<wire::AllTypesXunion> value, wire::DefaultEnum err, | 
 |       ::fidl::StringView forward_to_server, wire::RespondWith result_variant) { | 
 |     return client_->EchoXunionsWithError(std::move(value), err, std::move(forward_to_server), | 
 |                                          result_variant); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoTablePayload> EchoTablePayload( | 
 |       fidl_test_compatibility::wire::RequestTable payload) { | 
 |     return client_->EchoTablePayload(std::move(payload)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoTablePayloadWithError> EchoTablePayloadWithError( | 
 |       fidl_test_compatibility::wire::EchoEchoTablePayloadWithErrorRequest payload) { | 
 |     return client_->EchoTablePayloadWithError(std::move(payload)); | 
 |   } | 
 |  | 
 |   fidl::Status EchoTablePayloadNoRetVal(fidl_test_compatibility::wire::RequestTable payload, | 
 |                                         fidl::WireSyncEventHandler<Echo>& event_handler) { | 
 |     auto result = client_->EchoTablePayloadNoRetVal(std::move(payload)); | 
 |     if (!result.ok()) { | 
 |       return result; | 
 |     } | 
 |     return client_.HandleOneEvent(event_handler); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoTableRequestComposed> EchoTableRequestComposed( | 
 |       ::fidl_test_imported::wire::ComposedEchoTableRequestComposedRequest payload) { | 
 |     return client_->EchoTableRequestComposed(std::move(payload)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoUnionPayload> EchoUnionPayload( | 
 |       fidl_test_compatibility::wire::RequestUnion payload) { | 
 |     return client_->EchoUnionPayload(std::move(payload)); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoUnionPayloadWithError> EchoUnionPayloadWithError( | 
 |       fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest payload) { | 
 |     return client_->EchoUnionPayloadWithError(std::move(payload)); | 
 |   } | 
 |  | 
 |   fidl::Status EchoUnionPayloadNoRetVal(fidl_test_compatibility::wire::RequestUnion payload, | 
 |                                         fidl::WireSyncEventHandler<Echo>& event_handler) { | 
 |     auto result = client_->EchoUnionPayloadNoRetVal(std::move(payload)); | 
 |     if (!result.ok()) { | 
 |       return result; | 
 |     } | 
 |     return client_.HandleOneEvent(event_handler); | 
 |   } | 
 |  | 
 |   fidl::WireResult<Echo::EchoUnionResponseWithErrorComposed> EchoUnionResponseWithErrorComposed( | 
 |       int64_t value, bool want_absolute_value, ::fidl::StringView forward_to_server, | 
 |       uint32_t result_err, fidl_test_imported::wire::WantResponse result_variant) { | 
 |     return client_->EchoUnionResponseWithErrorComposed( | 
 |         value, want_absolute_value, forward_to_server, result_err, result_variant); | 
 |   } | 
 |  | 
 |   EchoClientApp(const EchoClientApp&) = delete; | 
 |   EchoClientApp& operator=(const EchoClientApp&) = delete; | 
 |  | 
 |  private: | 
 |   // Called once upon construction to connect to the server. | 
 |   ::fidl::ClientEnd<fidl_test_compatibility::Echo> ConnectTo() { | 
 |     auto context = sys::ComponentContext::Create(); | 
 |     auto echo_ends = ::fidl::CreateEndpoints<fidl_test_compatibility::Echo>(); | 
 |     { | 
 |       zx_status_t status = | 
 |           context->svc()->Connect(kEchoInterfaceName, echo_ends->server.TakeChannel()); | 
 |       ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status)); | 
 |     } | 
 |  | 
 |     return std::move(echo_ends->client); | 
 |   } | 
 |  | 
 |   std::unique_ptr<sys::ComponentContext> context_; | 
 |   fidl::WireSyncClient<Echo> client_; | 
 | }; | 
 |  | 
 | class EchoSyncEventHandlerTestStub : public fidl::testing::WireSyncEventHandlerTestBase<Echo> { | 
 |  public: | 
 |   void NotImplemented_(const std::string& name) final { ZX_PANIC("Unexpected %s", name.c_str()); } | 
 | }; | 
 |  | 
 | class EchoConnection final : public fidl::WireServer<Echo> { | 
 |  public: | 
 |   EchoConnection() = default; | 
 |  | 
 |   void EchoMinimal(EchoMinimalRequestView request, EchoMinimalCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       completer.Reply(); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoMinimal(""); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoMinimalWithError(EchoMinimalWithErrorRequestView request, | 
 |                             EchoMinimalWithErrorCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(0u); | 
 |       } else { | 
 |         completer.ReplySuccess(); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoMinimalWithError("", request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoMinimalNoRetVal(EchoMinimalNoRetValRequestView request, | 
 |                            EchoMinimalNoRetValCompleter::Sync&) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       fidl::Status result = fidl::WireSendEvent(server_binding_.value())->EchoMinimalEvent(); | 
 |       ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s", | 
 |                     result.FormatDescription().c_str()); | 
 |     } else { | 
 |       class EventHandler : public EchoSyncEventHandlerTestStub { | 
 |        public: | 
 |         explicit EventHandler(EchoConnection* connection) : connection_(connection) {} | 
 |  | 
 |         fidl::Status result() const { return result_; } | 
 |  | 
 |         void EchoMinimalEvent() override { | 
 |           result_ = fidl::WireSendEvent(connection_->server_binding_.value())->EchoMinimalEvent(); | 
 |         } | 
 |  | 
 |        private: | 
 |         EchoConnection* const connection_; | 
 |         fidl::Status result_ = fidl::Status::Ok(); | 
 |       }; | 
 |  | 
 |       EchoClientApp app; | 
 |       EventHandler event_handler(this); | 
 |       fidl::Status status = app.EchoMinimalNoRetVal("", event_handler); | 
 |       ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s", | 
 |                     status.FormatDescription().c_str()); | 
 |       ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s", | 
 |                     event_handler.result().FormatDescription().c_str()); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoStruct(EchoStructRequestView request, EchoStructCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       completer.Reply(std::move(request->value)); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoStruct(std::move(request->value), ""); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(result->value)); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoStructWithError(EchoStructWithErrorRequestView request, | 
 |                            EchoStructWithErrorCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(request->result_err); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(request->value)); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoStructWithError(std::move(request->value), request->result_err, "", | 
 |                                             request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(result.value().value()->value)); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoStructNoRetVal(EchoStructNoRetValRequestView request, | 
 |                           EchoStructNoRetValCompleter::Sync&) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       fidl::Status result = | 
 |           fidl::WireSendEvent(server_binding_.value())->EchoEvent(std::move(request->value)); | 
 |       ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s", | 
 |                     result.FormatDescription().c_str()); | 
 |     } else { | 
 |       class EventHandler : public EchoSyncEventHandlerTestStub { | 
 |        public: | 
 |         explicit EventHandler(EchoConnection* connection) : connection_(connection) {} | 
 |  | 
 |         fidl::Status result() const { return result_; } | 
 |  | 
 |         void EchoEvent(fidl::WireEvent<Echo::EchoEvent>* event) override { | 
 |           result_ = fidl::WireSendEvent(connection_->server_binding_.value()) | 
 |                         ->EchoEvent(std::move(event->value)); | 
 |         } | 
 |  | 
 |        private: | 
 |         EchoConnection* const connection_; | 
 |         fidl::Status result_ = fidl::Status::Ok(); | 
 |       }; | 
 |  | 
 |       EchoClientApp app; | 
 |       EventHandler event_handler(this); | 
 |       fidl::Status status = app.EchoStructNoRetVal(std::move(request->value), "", event_handler); | 
 |       ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s", | 
 |                     status.FormatDescription().c_str()); | 
 |       ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s", | 
 |                     event_handler.result().FormatDescription().c_str()); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoArrays(EchoArraysRequestView request, EchoArraysCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       completer.Reply(std::move(request->value)); | 
 |     } else { | 
 |       fidl::SyncClientBuffer<Echo::EchoArrays> buffer; | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoArrays(buffer.view(), std::move(request->value), ""); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(result->value)); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoArraysWithError(EchoArraysWithErrorRequestView request, | 
 |                            EchoArraysWithErrorCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(request->result_err); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(request->value)); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoArraysWithError(std::move(request->value), request->result_err, "", | 
 |                                             request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(result.value().value()->value)); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoVectors(EchoVectorsRequestView request, EchoVectorsCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       completer.Reply(std::move(request->value)); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoVectors(std::move(request->value), ""); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(result->value)); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoVectorsWithError(EchoVectorsWithErrorRequestView request, | 
 |                             EchoVectorsWithErrorCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(request->result_err); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(request->value)); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoVectorsWithError(std::move(request->value), request->result_err, "", | 
 |                                              request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(result.value().value()->value)); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoTable(EchoTableRequestView request, EchoTableCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       completer.Reply(request->value); | 
 |     } else { | 
 |       fidl::SyncClientBuffer<Echo::EchoTable> buffer; | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoTable(buffer.view(), request->value, ""); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(result->value); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoTableWithError(EchoTableWithErrorRequestView request, | 
 |                           EchoTableWithErrorCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(request->result_err); | 
 |       } else { | 
 |         completer.ReplySuccess(request->value); | 
 |       } | 
 |     } else { | 
 |       fidl::SyncClientBuffer<Echo::EchoTableWithError> buffer; | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoTableWithError(buffer.view(), request->value, request->result_err, "", | 
 |                                            request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(result.value().value()->value)); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoXunions(EchoXunionsRequestView request, EchoXunionsCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       completer.Reply(std::move(request->value)); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoXunions(std::move(request->value), ""); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(result->value)); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoXunionsWithError(EchoXunionsWithErrorRequestView request, | 
 |                             EchoXunionsWithErrorCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(request->result_err); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(request->value)); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoXunionsWithError(std::move(request->value), request->result_err, "", | 
 |                                              request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(result.value().value()->value)); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoNamedStruct(EchoNamedStructRequestView request, | 
 |                        EchoNamedStructCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       completer.Reply(std::move(request->value)); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoNamedStruct(std::move(request->value), ""); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(result->value)); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoNamedStructWithError(EchoNamedStructWithErrorRequestView request, | 
 |                                 EchoNamedStructWithErrorCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == fidl_test_imported::wire::WantResponse::kErr) { | 
 |         completer.ReplyError(request->result_err); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(request->value)); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = app.EchoNamedStructWithError(std::move(request->value), request->result_err, "", | 
 |                                                  request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(std::move(result.value().value()->value)); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoNamedStructNoRetVal(EchoNamedStructNoRetValRequestView request, | 
 |                                EchoNamedStructNoRetValCompleter::Sync&) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       fidl::Status result = | 
 |           fidl::WireSendEvent(server_binding_.value())->OnEchoNamedEvent(std::move(request->value)); | 
 |       ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s", | 
 |                     result.FormatDescription().c_str()); | 
 |     } else { | 
 |       class EventHandler : public EchoSyncEventHandlerTestStub { | 
 |        public: | 
 |         explicit EventHandler(EchoConnection* connection) : connection_(connection) {} | 
 |  | 
 |         fidl::Status result() const { return result_; } | 
 |  | 
 |         void OnEchoNamedEvent(fidl::WireEvent<Echo::OnEchoNamedEvent>* event) override { | 
 |           result_ = fidl::WireSendEvent(connection_->server_binding_.value()) | 
 |                         ->OnEchoNamedEvent(std::move(event->value)); | 
 |         } | 
 |  | 
 |        private: | 
 |         EchoConnection* const connection_; | 
 |         fidl::Status result_ = fidl::Status::Ok(); | 
 |       }; | 
 |  | 
 |       EchoClientApp app; | 
 |       EventHandler event_handler(this); | 
 |       fidl::Status status = app.EchoNamedStructNoRetVal(request->value, "", event_handler); | 
 |       ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s", | 
 |                     status.FormatDescription().c_str()); | 
 |       ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s", | 
 |                     event_handler.result().FormatDescription().c_str()); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoTablePayload(EchoTablePayloadRequestView request, | 
 |                         EchoTablePayloadCompleter::Sync& completer) override { | 
 |     if (!request->has_forward_to_server()) { | 
 |       fidl::Arena allocator; | 
 |       completer.Reply(fidl_test_compatibility::wire::ResponseTable::Builder(allocator) | 
 |                           .value(request->value()) | 
 |                           .Build()); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       fidl::Arena allocator; | 
 |       ; | 
 |       auto result = | 
 |           app.EchoTablePayload(fidl_test_compatibility::wire::RequestTable::Builder(allocator) | 
 |                                    .value(request->value()) | 
 |                                    .Build()); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(*result.Unwrap())); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoTablePayloadWithError(EchoTablePayloadWithErrorRequestView request, | 
 |                                  EchoTablePayloadWithErrorCompleter::Sync& completer) override { | 
 |     if (!request->has_forward_to_server()) { | 
 |       if (request->result_variant() == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(request->result_err()); | 
 |       } else { | 
 |         fidl::Arena allocator; | 
 |  | 
 |         wire::EchoEchoTablePayloadWithErrorResult res = | 
 |             wire::EchoEchoTablePayloadWithErrorResult::WithResponse( | 
 |                 allocator, wire::ResponseTable::Builder(allocator).value(request->value()).Build()); | 
 |         completer.Reply(::fit::ok(&res.response())); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       fidl::Arena allocator; | 
 |       auto builder = wire::EchoEchoTablePayloadWithErrorRequest::Builder(allocator); | 
 |       builder.result_variant(request->result_variant()); | 
 |       if (request->result_variant() == wire::RespondWith::kErr) { | 
 |         builder.result_err(request->result_err()); | 
 |       } else { | 
 |         builder.value(request->value()); | 
 |       } | 
 |  | 
 |       auto result = app.EchoTablePayloadWithError(builder.Build()); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(*result.value().value()); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoTablePayloadNoRetVal(EchoTablePayloadNoRetValRequestView request, | 
 |                                 EchoTablePayloadNoRetValCompleter::Sync&) override { | 
 |     if (!request->has_forward_to_server()) { | 
 |       fidl::Arena allocator; | 
 |       fidl::Status result = | 
 |           fidl::WireSendEvent(server_binding_.value()) | 
 |               ->OnEchoTablePayloadEvent( | 
 |                   wire::ResponseTable::Builder(allocator).value(request->value()).Build()); | 
 |       ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s", | 
 |                     result.FormatDescription().c_str()); | 
 |     } else { | 
 |       class EventHandler : public EchoSyncEventHandlerTestStub { | 
 |        public: | 
 |         explicit EventHandler(EchoConnection* connection) : connection_(connection) {} | 
 |  | 
 |         fidl::Status result() const { return result_; } | 
 |  | 
 |         void OnEchoTablePayloadEvent( | 
 |             fidl::WireEvent<Echo::OnEchoTablePayloadEvent>* event) override { | 
 |           result_ = fidl::WireSendEvent(connection_->server_binding_.value()) | 
 |                         ->OnEchoTablePayloadEvent(*event); | 
 |         } | 
 |  | 
 |        private: | 
 |         EchoConnection* const connection_; | 
 |         fidl::Status result_ = fidl::Status::Ok(); | 
 |       }; | 
 |  | 
 |       EchoClientApp app; | 
 |       EventHandler event_handler(this); | 
 |       fidl::Arena allocator; | 
 |       fidl::Status status = app.EchoTablePayloadNoRetVal( | 
 |           wire::RequestTable::Builder(allocator).value(request->value()).Build(), event_handler); | 
 |       ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s", | 
 |                     status.FormatDescription().c_str()); | 
 |       ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s", | 
 |                     event_handler.result().FormatDescription().c_str()); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoTableRequestComposed(EchoTableRequestComposedRequestView request, | 
 |                                 EchoTableRequestComposedCompleter::Sync& completer) override { | 
 |     if (!request->has_forward_to_server()) { | 
 |       completer.Reply( | 
 |           std::move(fidl_test_imported::wire::SimpleStruct{.f1 = true, .f2 = request->value()})); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       fidl::Arena allocator; | 
 |  | 
 |       auto result = app.EchoTableRequestComposed( | 
 |           fidl_test_imported::wire::ComposedEchoTableRequestComposedRequest::Builder(allocator) | 
 |               .value(request->value()) | 
 |               .Build()); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(result->value)); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoUnionPayload(EchoUnionPayloadRequestView request, | 
 |                         EchoUnionPayloadCompleter::Sync& completer) override { | 
 |     fidl::StringView& forward_to_server = request->is_signed_() | 
 |                                               ? request->signed_().forward_to_server | 
 |                                               : request->unsigned_().forward_to_server; | 
 |     if (forward_to_server.empty()) { | 
 |       fidl::Arena allocator; | 
 |       fidl_test_compatibility::wire::ResponseUnion resp; | 
 |       if (request->is_signed_()) { | 
 |         resp = fidl_test_compatibility::wire::ResponseUnion::WithSigned_(allocator, | 
 |                                                                          request->signed_().value); | 
 |       } else { | 
 |         resp = fidl_test_compatibility::wire::ResponseUnion::WithUnsigned_( | 
 |             allocator, request->unsigned_().value); | 
 |       } | 
 |       completer.Reply(std::move(resp)); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       fidl::Arena allocator; | 
 |       fidl_test_compatibility::wire::RequestUnion req; | 
 |  | 
 |       if (request->is_signed_()) { | 
 |         req = | 
 |             fidl_test_compatibility::wire::RequestUnion::WithSigned_(allocator, request->signed_()); | 
 |         req.signed_().forward_to_server = ""; | 
 |       } else { | 
 |         req = fidl_test_compatibility::wire::RequestUnion::WithUnsigned_(allocator, | 
 |                                                                          request->unsigned_()); | 
 |         req.unsigned_().forward_to_server = ""; | 
 |       } | 
 |       auto result = app.EchoUnionPayload(req); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       completer.Reply(std::move(*result.Unwrap())); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoUnionPayloadWithError(EchoUnionPayloadWithErrorRequestView request, | 
 |                                  EchoUnionPayloadWithErrorCompleter::Sync& completer) override { | 
 |     fidl::StringView& forward_to_server = request->is_signed_() | 
 |                                               ? request->signed_().forward_to_server | 
 |                                               : request->unsigned_().forward_to_server; | 
 |     wire::RespondWith& result_variant = request->is_signed_() ? request->signed_().result_variant | 
 |                                                               : request->unsigned_().result_variant; | 
 |     if (forward_to_server.empty()) { | 
 |       if (result_variant == wire::RespondWith::kErr) { | 
 |         completer.ReplyError(request->is_signed_() ? request->signed_().result_err | 
 |                                                    : request->unsigned_().result_err); | 
 |       } else { | 
 |         fidl::Arena allocator; | 
 |         fidl_test_compatibility::wire::ResponseUnion resp; | 
 |         if (request->is_signed_()) { | 
 |           resp = fidl_test_compatibility::wire::ResponseUnion::WithSigned_( | 
 |               allocator, request->signed_().value); | 
 |         } else { | 
 |           resp = fidl_test_compatibility::wire::ResponseUnion::WithUnsigned_( | 
 |               allocator, request->unsigned_().value); | 
 |         } | 
 |         completer.ReplySuccess(resp); | 
 |       } | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       fidl::Arena allocator; | 
 |       fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest req; | 
 |  | 
 |       if (request->is_signed_()) { | 
 |         req = fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest::WithSigned_( | 
 |             allocator, request->signed_()); | 
 |         req.signed_().forward_to_server = ""; | 
 |       } else { | 
 |         req = fidl_test_compatibility::wire::EchoEchoUnionPayloadWithErrorRequest::WithUnsigned_( | 
 |             allocator, request->unsigned_()); | 
 |         req.unsigned_().forward_to_server = ""; | 
 |       } | 
 |       auto result = app.EchoUnionPayloadWithError(req); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(*result.value().value()); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoUnionPayloadNoRetVal(EchoUnionPayloadNoRetValRequestView request, | 
 |                                 EchoUnionPayloadNoRetValCompleter::Sync&) override { | 
 |     fidl::StringView& forward_to_server = request->is_signed_() | 
 |                                               ? request->signed_().forward_to_server | 
 |                                               : request->unsigned_().forward_to_server; | 
 |     if (forward_to_server.empty()) { | 
 |       fidl::Arena allocator; | 
 |       fidl_test_compatibility::wire::ResponseUnion resp; | 
 |       if (request->is_signed_()) { | 
 |         resp = fidl_test_compatibility::wire::ResponseUnion::WithSigned_(allocator, | 
 |                                                                          request->signed_().value); | 
 |       } else { | 
 |         resp = fidl_test_compatibility::wire::ResponseUnion::WithUnsigned_( | 
 |             allocator, request->unsigned_().value); | 
 |       } | 
 |       fidl::Status result = | 
 |           fidl::WireSendEvent(server_binding_.value())->OnEchoUnionPayloadEvent(std::move(resp)); | 
 |       ZX_ASSERT_MSG(result.ok(), "Replying with event failed: %s", | 
 |                     result.FormatDescription().c_str()); | 
 |     } else { | 
 |       class EventHandler : public EchoSyncEventHandlerTestStub { | 
 |        public: | 
 |         explicit EventHandler(EchoConnection* connection) : connection_(connection) {} | 
 |  | 
 |         fidl::Status result() const { return result_; } | 
 |         void OnEchoUnionPayloadEvent( | 
 |             fidl::WireEvent<Echo::OnEchoUnionPayloadEvent>* event) override { | 
 |           result_ = fidl::WireSendEvent(connection_->server_binding_.value()) | 
 |                         ->OnEchoUnionPayloadEvent(*event); | 
 |         } | 
 |  | 
 |        private: | 
 |         EchoConnection* const connection_; | 
 |         fidl::Status result_ = fidl::Status::Ok(); | 
 |       }; | 
 |  | 
 |       EchoClientApp app; | 
 |       EventHandler event_handler(this); | 
 |       fidl::Arena allocator; | 
 |       fidl_test_compatibility::wire::RequestUnion req; | 
 |  | 
 |       if (request->is_signed_()) { | 
 |         req = | 
 |             fidl_test_compatibility::wire::RequestUnion::WithSigned_(allocator, request->signed_()); | 
 |         req.signed_().forward_to_server = ""; | 
 |       } else { | 
 |         req = fidl_test_compatibility::wire::RequestUnion::WithUnsigned_(allocator, | 
 |                                                                          request->unsigned_()); | 
 |         req.unsigned_().forward_to_server = ""; | 
 |       } | 
 |       fidl::Status status = app.EchoUnionPayloadNoRetVal(req, event_handler); | 
 |       ZX_ASSERT_MSG(status.ok(), "Replying with event failed direct: %s", | 
 |                     status.FormatDescription().c_str()); | 
 |       ZX_ASSERT_MSG(event_handler.result().ok(), "Replying with event failed indirect: %s", | 
 |                     event_handler.result().FormatDescription().c_str()); | 
 |     } | 
 |   } | 
 |  | 
 |   void EchoUnionResponseWithErrorComposed( | 
 |       EchoUnionResponseWithErrorComposedRequestView request, | 
 |       EchoUnionResponseWithErrorComposedCompleter::Sync& completer) override { | 
 |     if (request->forward_to_server.empty()) { | 
 |       if (request->result_variant == fidl_test_imported::wire::WantResponse::kErr) { | 
 |         completer.ReplyError(request->result_err); | 
 |         return; | 
 |       } | 
 |       fidl::Arena allocator; | 
 |       fidl_test_imported::wire::ComposedEchoUnionResponseWithErrorComposedResponse resp; | 
 |       if (request->want_absolute_value) { | 
 |         auto obj_view = | 
 |             fidl::ObjectView<uint64_t>(allocator, static_cast<uint64_t>(std::abs(request->value))); | 
 |         resp = fidl_test_imported::wire::ComposedEchoUnionResponseWithErrorComposedResponse:: | 
 |             WithUnsigned_(std::move(obj_view)); | 
 |       } else { | 
 |         auto obj_view = fidl::ObjectView<int64_t>(allocator, request->value); | 
 |         resp = fidl_test_imported::wire::ComposedEchoUnionResponseWithErrorComposedResponse:: | 
 |             WithSigned_(std::move(obj_view)); | 
 |       } | 
 |       completer.ReplySuccess(resp); | 
 |     } else { | 
 |       EchoClientApp app; | 
 |       auto result = | 
 |           app.EchoUnionResponseWithErrorComposed(request->value, request->want_absolute_value, "", | 
 |                                                  request->result_err, request->result_variant); | 
 |       ZX_ASSERT_MSG(result.ok(), "Forwarding failed: %s", result.FormatDescription().c_str()); | 
 |       if (result.value().is_error()) { | 
 |         completer.ReplyError(result.value().error_value()); | 
 |       } else { | 
 |         completer.ReplySuccess(*result.value().value()); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   void set_server_binding(::fidl::ServerBindingRef<Echo> binding) { | 
 |     server_binding_.emplace(binding); | 
 |   } | 
 |  | 
 |  private: | 
 |   std::optional<::fidl::ServerBindingRef<Echo>> server_binding_; | 
 | }; | 
 |  | 
 | int main(int argc, const char** argv) { | 
 |   // The FIDL support lib requires async_get_default_dispatcher() to return | 
 |   // non-null. | 
 |   async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread); | 
 |   auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory(); | 
 |   std::vector<std::unique_ptr<EchoConnection>> connections; | 
 |  | 
 |   context->outgoing()->AddPublicService( | 
 |       std::make_unique<vfs::Service>([&](zx::channel request, async_dispatcher_t* dispatcher) { | 
 |         auto conn = std::make_unique<EchoConnection>(); | 
 |         auto binding = ::fidl::BindServer( | 
 |             dispatcher, ::fidl::ServerEnd<fidl_test_compatibility::Echo>(std::move(request)), | 
 |             conn.get()); | 
 |         conn->set_server_binding(std::move(binding)); | 
 |         connections.push_back(std::move(conn)); | 
 |       }), | 
 |       kEchoInterfaceName); | 
 |  | 
 |   loop.Run(); | 
 |   return EXIT_SUCCESS; | 
 | } |