// Copyright 2020 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.

#ifndef LIB_FIDL_LLCPP_MESSAGE_H_
#define LIB_FIDL_LLCPP_MESSAGE_H_

#include <lib/fidl/cpp/transaction_header.h>
#include <lib/fidl/cpp/wire_format_metadata.h>
#include <lib/fidl/llcpp/internal/transport.h>
#include <lib/fidl/llcpp/message_storage.h>
#include <lib/fidl/llcpp/status.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/fit/nullable.h>
#include <lib/fitx/result.h>
#include <zircon/assert.h>
#include <zircon/fidl.h>

#include <array>
#include <memory>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>

#ifdef __Fuchsia__
#include <lib/fidl/llcpp/internal/endpoints.h>
#include <lib/zx/channel.h>
#endif  // __Fuchsia__

namespace fidl_testing {
// Forward declaration of test helpers to support friend declaration.
class MessageChecker;
}  // namespace fidl_testing

namespace fidl {

namespace internal {

constexpr WireFormatVersion kLLCPPWireFormatVersion = WireFormatVersion::kV2;

// Marker to allow references/pointers to the unowned input objects in OwnedEncodedMessage.
// This enables iovec optimizations but requires the input objects to stay in scope until the
// encoded result has been consumed.
struct AllowUnownedInputRef {};

}  // namespace internal

// |OutgoingMessage| represents a FIDL message on the write path.
//
// This class does not allocate its own memory storage. Instead, users need to
// pass in encoding buffers of sufficient size, which an |OutgoingMessage| will
// borrow until its destruction.
//
// This class takes ownership of handles in the message.
//
// For efficiency, errors are stored inside this object. |Write| operations are
// no-op and return the contained error if the message is in an error state.
class OutgoingMessage : public ::fidl::Status {
 public:
  // Copy and move is disabled for the sake of avoiding double handle close.
  // It is possible to implement the move operations with correct semantics if they are
  // ever needed.
  OutgoingMessage(const OutgoingMessage&) = delete;
  OutgoingMessage(OutgoingMessage&&) = delete;
  OutgoingMessage& operator=(const OutgoingMessage&) = delete;
  OutgoingMessage& operator=(OutgoingMessage&&) = delete;
  OutgoingMessage() = delete;
  ~OutgoingMessage();

  // Creates an object which can manage a FIDL message. This should only be used
  // when interfacing with C APIs. |c_msg| must contain an already-encoded
  // message. The handles in |c_msg| are owned by the returned |OutgoingMessage|
  // object.
  //
  // Only the channel transport is supported for C messages. For other transports,
  // use other constructors of |OutgoingMessage|.
  //
  // The bytes must represent a transactional message.
  static OutgoingMessage FromEncodedCMessage(const fidl_outgoing_msg_t* c_msg);

  // Creates an object which can manage an encoded FIDL value.
  // This is identical to |FromEncodedCMessage| but the |OutgoingMessage|
  // is non-transactional instead of transactional.
  static OutgoingMessage FromEncodedCValue(const fidl_outgoing_msg_t* c_msg);

  struct InternalIovecConstructorArgs {
    const internal::TransportVTable* transport_vtable;
    zx_channel_iovec_t* iovecs;
    uint32_t iovec_capacity;
    fidl_handle_t* handles;
    fidl_handle_metadata_t* handle_metadata;
    uint32_t handle_capacity;
    uint8_t* backing_buffer;
    uint32_t backing_buffer_capacity;
    bool is_transactional;
  };
  // Creates an object which can manage a FIDL message.
  // |args.iovecs|, |args.handles| and |args.backing_buffer| contain undefined data that will be
  // populated during |Encode|.
  // Internal-only function that should not be called outside of the FIDL library.
  static OutgoingMessage Create_InternalMayBreak(InternalIovecConstructorArgs args) {
    return OutgoingMessage(args);
  }

  struct InternalByteBackedConstructorArgs {
    const internal::TransportVTable* transport_vtable;
    uint8_t* bytes;
    uint32_t num_bytes;
    fidl_handle_t* handles;
    fidl_handle_metadata_t* handle_metadata;
    uint32_t num_handles;
    bool is_transactional;
  };

  // Creates an object which can manage a FIDL message or body.
  // |args.bytes| and |args.handles| should already contain encoded data.
  // Internal-only function that should not be called outside of the FIDL library.
  static OutgoingMessage Create_InternalMayBreak(InternalByteBackedConstructorArgs args) {
    return OutgoingMessage(args);
  }

  // Creates an empty outgoing message representing an error.
  //
  // |failure| must contain an error result.
  explicit OutgoingMessage(const ::fidl::Status& failure);

  // Set the txid in the message header.
  //
  // Requires that the message is encoded, and is a transactional message.
  // Requires that there are sufficient bytes to store the header in the buffer.
  void set_txid(zx_txid_t txid) {
    if (!ok()) {
      return;
    }
    ZX_ASSERT(is_transactional_);
    ZX_ASSERT(iovec_actual() >= 1 && iovecs()[0].capacity >= sizeof(fidl_message_header_t));
    // The byte buffer is const because the kernel only reads the bytes.
    // const_cast is needed to populate it here.
    static_cast<fidl_message_header_t*>(const_cast<void*>(iovecs()[0].buffer))->txid = txid;
  }

  zx_channel_iovec_t* iovecs() const { return iovec_message().iovecs; }
  uint32_t iovec_actual() const { return iovec_message().num_iovecs; }
  fidl_handle_t* handles() const { return iovec_message().handles; }
  fidl_transport_type transport_type() const { return transport_vtable_->type; }
  uint32_t handle_actual() const { return iovec_message().num_handles; }

  template <typename Transport>
  typename Transport::HandleMetadata* handle_metadata() const {
    ZX_ASSERT(Transport::VTable.type == transport_vtable_->type);
    return reinterpret_cast<typename Transport::HandleMetadata*>(iovec_message().handle_metadata);
  }

  // Convert the outgoing message to its C API counterpart, releasing the
  // ownership of handles to the caller in the process. This consumes the
  // |OutgoingMessage|.
  //
  // This should only be called while the message is in its encoded form.
  fidl_outgoing_msg_t ReleaseToEncodedCMessage() &&;

  // Returns true iff the bytes in this message are identical to the bytes in the argument.
  bool BytesMatch(const OutgoingMessage& other) const;

  // Holds a heap-allocated contiguous copy of the bytes in this message.
  //
  // This owns the allocated buffer and frees it when the object goes out of scope.
  // To create a |CopiedBytes|, use |CopyBytes|.
  class CopiedBytes {
   public:
    CopiedBytes() = default;
    CopiedBytes(CopiedBytes&&) = default;
    CopiedBytes& operator=(CopiedBytes&&) = default;
    CopiedBytes(const CopiedBytes&) = delete;
    CopiedBytes& operator=(const CopiedBytes&) = delete;

    uint8_t* data() { return bytes_.data(); }
    size_t size() const { return bytes_.size(); }

   private:
    explicit CopiedBytes(const OutgoingMessage& msg);

    std::vector<uint8_t> bytes_;

    friend class OutgoingMessage;
  };

  // Create a heap-allocated contiguous copy of the bytes in this message.
  CopiedBytes CopyBytes() const { return CopiedBytes(*this); }

  // Release the handles to prevent them to be closed by CloseHandles. This method is only useful
  // when interfacing with low-level channel operations which consume the handles.
  void ReleaseHandles() { iovec_message().num_handles = 0; }

  // Encodes the data.
  template <typename FidlType>
  void Encode(FidlType* data) {
    Encode(fidl::internal::WireFormatVersion::kV2, fidl::TypeTraits<FidlType>::kType, data);
  }

  template <typename FidlType>
  void Encode(fidl::internal::WireFormatVersion wire_format_version, FidlType* data) {
    is_transactional_ = fidl::IsFidlTransactionalMessage<FidlType>::value;
    EncodeImpl(wire_format_version, fidl::TypeTraits<FidlType>::kType, data);
  }

  // Various helper functions for writing to other channel-like types.

  void Write(internal::AnyUnownedTransport transport, WriteOptions options = {});

  template <typename TransportObject>
  void Write(TransportObject&& transport, WriteOptions options = {}) {
    Write(internal::MakeAnyUnownedTransport(std::forward<TransportObject>(transport)),
          std::move(options));
  }

  // Makes a call on a transport that expects the caller to provide read
  // buffers, then decodes them.
  // TODO(fxbug.dev/60240): To support both wire and natural types using the
  // same calling mechanism, decoding should be domain object family-specific
  // and moved out of |Call|.
  template <typename FidlType, typename TransportObject,
            typename = std::enable_if_t<
                !internal::AssociatedTransport<TransportObject>::kTransportProvidesReadBuffer>>
  void Call(TransportObject&& transport, uint8_t* result_bytes, uint32_t result_byte_capacity,
            CallOptions options = {}) {
    fidl_handle_t result_handles[ZX_CHANNEL_MAX_MSG_HANDLES];
    typename internal::AssociatedTransport<TransportObject>::HandleMetadata
        result_handle_metadata[ZX_CHANNEL_MAX_MSG_HANDLES];
    CallImplForCallerProvidedBuffer(
        internal::MakeAnyUnownedTransport(std::forward<TransportObject>(transport)),
        fidl::TypeTraits<FidlType>::kType, result_bytes, result_byte_capacity, result_handles,
        reinterpret_cast<fidl_handle_metadata_t*>(result_handle_metadata),
        ZX_CHANNEL_MAX_MSG_HANDLES, std::move(options));
  }

  // Makes a call on a transport whose messages read are associated with their
  // own buffers, then decodes them.
  // TODO(fxbug.dev/60240): To support both wire and natural types using the
  // same calling mechanism, decoding should be domain object family-specific
  // and moved out of |Call|.
  template <typename FidlType, typename TransportObject,
            typename = std::enable_if_t<
                internal::AssociatedTransport<TransportObject>::kTransportProvidesReadBuffer>>
  void Call(TransportObject&& transport, uint8_t** out_bytes, uint32_t* out_num_bytes,
            CallOptions options = {}) {
    CallImplForTransportProvidedBuffer(
        internal::MakeAnyUnownedTransport(std::forward<TransportObject>(transport)),
        fidl::TypeTraits<FidlType>::kType, out_bytes, out_num_bytes, std::move(options));
  }

  // Makes a call and returns the response read from the transport, without
  // decoding.
  // TODO(fxbug.dev/60240): Move every user to this overload of |Call|.
  template <typename TransportObject>
  auto Call(TransportObject&& transport,
            typename internal::AssociatedTransport<TransportObject>::MessageStorageView storage,
            CallOptions options = {}) {
    return CallImpl(internal::MakeAnyUnownedTransport(std::forward<TransportObject>(transport)),
                    static_cast<internal::MessageStorageViewBase&>(storage), std::move(options));
  }

  bool is_transactional() const { return is_transactional_; }

 protected:
  OutgoingMessage(fidl_outgoing_msg_t msg, uint32_t handle_capacity)
      : ::fidl::Status(::fidl::Status::Ok()), message_(msg), handle_capacity_(handle_capacity) {}

  void EncodeImpl(fidl::internal::WireFormatVersion wire_format_version,
                  const fidl_type_t* message_type, void* data);

  uint32_t iovec_capacity() const { return iovec_capacity_; }
  uint32_t handle_capacity() const { return handle_capacity_; }
  uint32_t backing_buffer_capacity() const { return backing_buffer_capacity_; }
  uint8_t* backing_buffer() const { return backing_buffer_; }

 private:
  friend ::fidl_testing::MessageChecker;

  explicit OutgoingMessage(InternalIovecConstructorArgs args);
  explicit OutgoingMessage(InternalByteBackedConstructorArgs args);
  explicit OutgoingMessage(const fidl_outgoing_msg_t* msg, bool is_transactional);

  void DecodeImplForCall(const internal::CodingConfig& coding_config,
                         const fidl_type_t* response_type, uint8_t* bytes,
                         uint32_t* in_out_num_bytes, fidl_handle_t* handles,
                         fidl_handle_metadata_t* handle_metadata, uint32_t num_handles);

  void CallImplForCallerProvidedBuffer(internal::AnyUnownedTransport transport,
                                       const fidl_type_t* response_type, uint8_t* result_bytes,
                                       uint32_t result_byte_capacity, fidl_handle_t* result_handles,
                                       fidl_handle_metadata_t* result_handle_metadata,
                                       uint32_t result_handle_capacity, CallOptions options);

  void CallImplForTransportProvidedBuffer(internal::AnyUnownedTransport transport,
                                          const fidl_type_t* response_type, uint8_t** out_bytes,
                                          uint32_t* out_num_bytes, CallOptions options);

  fidl::IncomingMessage CallImpl(internal::AnyUnownedTransport transport,
                                 internal::MessageStorageViewBase& storage, CallOptions options);

  fidl_outgoing_msg_iovec_t& iovec_message() {
    ZX_DEBUG_ASSERT(message_.type == FIDL_OUTGOING_MSG_TYPE_IOVEC);
    return message_.iovec;
  }
  const fidl_outgoing_msg_iovec_t& iovec_message() const {
    ZX_DEBUG_ASSERT(message_.type == FIDL_OUTGOING_MSG_TYPE_IOVEC);
    return message_.iovec;
  }

  using Status::SetStatus;

  const internal::TransportVTable* transport_vtable_ = nullptr;
  fidl_outgoing_msg_t message_ = {};
  uint32_t iovec_capacity_ = 0;
  uint32_t handle_capacity_ = 0;
  uint32_t backing_buffer_capacity_ = 0;
  uint8_t* backing_buffer_ = nullptr;

  // If OutgoingMessage is constructed with a fidl_outgoing_msg_t* that contains bytes
  // rather than iovec, it is converted to a single-element iovec pointing to the bytes.
  zx_channel_iovec_t converted_byte_message_iovec_ = {};
  bool is_transactional_ = false;
};

namespace internal {

template <typename T>
class DecodedMessageBase;

class NaturalDecoder;

}  // namespace internal

// |IncomingMessage| represents a FIDL message on the read path.
// Each instantiation of the class should only be used for one message.
//
// |IncomingMessage|s are created with the results from reading from a channel.
// By default, it assumes it is a transactional message, and automatically
// performs necessary validation on the message header - users may opt out
// via the |kSkipMessageHeaderValidation| constructor overload in the case of
// regular FIDL type encoding/decoding.
//
// |IncomingMessage| relinquishes the ownership of the handles after decoding.
// Instead, callers must adopt the decoded content into another RAII class, such
// as |fidl::unstable::DecodedMessage<FidlType>|.
//
// Functions that take |IncomingMessage&| conditionally take ownership of the
// message. For functions in the public API, they must then indicate through
// their return value if they took ownership. For functions in the binding
// internals, it is sufficient to only document the conditions where minimum
// overhead is desired.
//
// Functions that take |IncomingMessage&&| always take ownership of the message.
// In practice, this means that they must either decode the message, or close
// the handles, or move the message into a deeper function that takes
// |IncomingMessage&&|.
//
// For efficiency, errors are stored inside this object. Callers must check for
// errors after construction, and after performing each operation on the object.
//
// An |IncomingMessage| may be created from |fidl::ChannelReadEtc|:
//
//     fidl::IncomingMessage msg = fidl::ChannelReadEtc(handle, 0, byte_span, handle_span);
//     if (!msg.ok()) { /* ... error handling ... */ }
//
class IncomingMessage : public ::fidl::Status {
 public:
  // Creates an object which can manage a FIDL channel message. Allocated memory is
  // not owned by the |IncomingMessage|, but handles are owned by it and cleaned up when the
  // |IncomingMessage| is destructed.
  //
  // The bytes must represent a transactional message. See
  // https://fuchsia.dev/fuchsia-src/reference/fidl/language/wire-format?hl=en#transactional-messages
  template <typename HandleMetadata>
  static IncomingMessage Create(uint8_t* bytes, uint32_t byte_actual, zx_handle_t* handles,
                                HandleMetadata* handle_metadata, uint32_t handle_actual) {
    return Create<typename internal::AssociatedTransport<HandleMetadata>>(
        bytes, byte_actual, handles, handle_metadata, handle_actual);
  }

  // Creates an object which can manage a FIDL message. Allocated memory is not owned by
  // the |IncomingMessage|, but handles are owned by it and cleaned up when the
  // |IncomingMessage| is destructed.
  //
  // The bytes must represent a transactional message. See
  // https://fuchsia.dev/fuchsia-src/reference/fidl/language/wire-format?hl=en#transactional-messages
  template <typename Transport>
  static IncomingMessage Create(uint8_t* bytes, uint32_t byte_actual, zx_handle_t* handles,
                                typename Transport::HandleMetadata* handle_metadata,
                                uint32_t handle_actual) {
    return IncomingMessage(&Transport::VTable, bytes, byte_actual, handles,
                           reinterpret_cast<fidl_handle_metadata_t*>(handle_metadata),
                           handle_actual);
  }

  // Creates an |IncomingMessage| from a C |fidl_incoming_msg_t| already in
  // encoded form. This should only be used when interfacing with C APIs.
  // The handles in |c_msg| are owned by the returned |IncomingMessage| object.
  //
  // The bytes must represent a transactional message.
  static IncomingMessage FromEncodedCMessage(const fidl_incoming_msg_t* c_msg);

  struct SkipMessageHeaderValidationTag {};

  // A marker that instructs the constructor of |IncomingMessage| to skip
  // validating the message header. This is useful when the message is not a
  // transactional message.
  constexpr inline static auto kSkipMessageHeaderValidation = SkipMessageHeaderValidationTag{};

  // An overload for when the bytes do not represent a transactional message.
  //
  // This constructor should be rarely used in practice. When decoding
  // FIDL types that are not transactional messages (e.g. tables), consider
  // using the constructor in |FidlType::DecodedMessage|, which delegates
  // here appropriately.
  template <typename HandleMetadata>
  static IncomingMessage Create(uint8_t* bytes, uint32_t byte_actual, zx_handle_t* handles,
                                HandleMetadata* handle_metadata, uint32_t handle_actual,
                                SkipMessageHeaderValidationTag) {
    return Create<internal::AssociatedTransport<HandleMetadata>>(
        bytes, byte_actual, handles, handle_metadata, handle_actual, kSkipMessageHeaderValidation);
  }

  // An overload for when the bytes do not represent a transactional message.
  //
  // This constructor should be rarely used in practice. When decoding
  // FIDL types that are not transactional messages (e.g. tables), consider
  // using the constructor in |FidlType::DecodedMessage|, which delegates
  // here appropriately.
  template <typename Transport>
  static IncomingMessage Create(uint8_t* bytes, uint32_t byte_actual, zx_handle_t* handles,
                                typename Transport::HandleMetadata* handle_metadata,
                                uint32_t handle_actual, SkipMessageHeaderValidationTag) {
    return IncomingMessage(&Transport::VTable, bytes, byte_actual, handles,
                           reinterpret_cast<fidl_handle_metadata_t*>(handle_metadata),
                           handle_actual, kSkipMessageHeaderValidation);
  }

  // Creates an empty incoming message representing an error (e.g. failed to read from
  // a channel).
  //
  // |failure| must contain an error result.
  static IncomingMessage Create(const ::fidl::Status& failure) { return IncomingMessage(failure); }

  IncomingMessage(const IncomingMessage&) = delete;
  IncomingMessage& operator=(const IncomingMessage&) = delete;

  IncomingMessage(IncomingMessage&& other) noexcept : ::fidl::Status(other) {
    MoveImpl(std::move(other));
  }
  IncomingMessage& operator=(IncomingMessage&& other) noexcept {
    ::fidl::Status::operator=(other);
    if (this != &other) {
      MoveImpl(std::move(other));
    }
    return *this;
  }

  ~IncomingMessage();

  fidl_message_header_t* header() const {
    ZX_DEBUG_ASSERT(ok());
    return reinterpret_cast<fidl_message_header_t*>(bytes());
  }

  // If the message is an epitaph, returns a pointer to the epitaph structure.
  // Otherwise, returns null.
  fit::nullable<fidl_epitaph_t*> maybe_epitaph() const {
    ZX_DEBUG_ASSERT(ok());
    if (unlikely(header()->ordinal == kFidlOrdinalEpitaph)) {
      return fit::nullable(reinterpret_cast<fidl_epitaph_t*>(bytes()));
    }
    return fit::nullable<fidl_epitaph_t*>{};
  }

  bool is_transactional() const { return is_transactional_; }

  uint8_t* bytes() const { return reinterpret_cast<uint8_t*>(message_.bytes); }
  uint32_t byte_actual() const { return message_.num_bytes; }

  zx_handle_t* handles() const { return message_.handles; }
  uint32_t handle_actual() const { return message_.num_handles; }

  template <typename Transport>
  typename Transport::HandleMetadata* handle_metadata() const {
    ZX_ASSERT(Transport::VTable.type == transport_vtable_->type);
    return reinterpret_cast<typename Transport::HandleMetadata*>(message_.handle_metadata);
  }

  // Convert the incoming message to its C API counterpart, releasing the
  // ownership of handles to the caller in the process. This consumes the
  // |IncomingMessage|.
  //
  // This should only be called while the message is in its encoded form.
  fidl_incoming_msg_t ReleaseToEncodedCMessage() &&;

  // Closes the handles managed by this message. This may be used when the
  // code would like to consume a |IncomingMessage&&| and close its handles,
  // but does not want to incur the overhead of moving it into a regular
  // |IncomingMessage| object, and running the destructor.
  //
  // This consumes the |IncomingMessage|.
  void CloseHandles() &&;

  // Consumes self and returns a new IncomingMessage with the transaction
  // header bytes skipped.
  IncomingMessage SkipTransactionHeader();

 private:
  explicit IncomingMessage(const ::fidl::Status& failure);
  IncomingMessage(const internal::TransportVTable* transport_vtable, uint8_t* bytes,
                  uint32_t byte_actual, zx_handle_t* handles,
                  fidl_handle_metadata_t* handle_metadata, uint32_t handle_actual);
  IncomingMessage(const internal::TransportVTable* transport_vtable, uint8_t* bytes,
                  uint32_t byte_actual, zx_handle_t* handles,
                  fidl_handle_metadata_t* handle_metadata, uint32_t handle_actual,
                  SkipMessageHeaderValidationTag);

  // Only |fidl::unstable::DecodedMessage<T>| instances may decode this message.
  template <typename T>
  friend class internal::DecodedMessageBase;

  friend class internal::NaturalDecoder;

  // |OutgoingMessage| may create an |IncomingMessage| with a dynamic transport during a call.
  friend class OutgoingMessage;

  // Decodes the message using |FidlType|. If this operation succeed, |status()| is ok and
  // |bytes()| contains the decoded object.
  //
  // The first 16 bytes of the message must be the FIDL message header and are used for
  // determining the wire format version for decoding.
  //
  // On success, the handles owned by |IncomingMessage| are transferred to the decoded bytes.
  // If a buffer needs to be allocated during decode, |out_transformed_buffer| will contain that
  // buffer. This buffer will be stored on DecodedMessageBase and stays in scope for the lifetime
  // of the decoded message, which is responsible for freeing it.
  //
  // This method should be used after a read.
  template <typename FidlType>
  void Decode() {
    ZX_ASSERT(is_transactional_);

    // If this is an empty message, there is nothing to decode, so exit early.
    if (fidl::TypeTraits<FidlType>::kType == nullptr) {
      return;
    }
    Decode(fidl::TypeTraits<FidlType>::kType);
  }

  // Decodes the message using |FidlType| for the specified |wire_format_version|. If this
  // operation succeed, |status()| is ok and |bytes()| contains the decoded object.
  //
  // On success, the handles owned by |IncomingMessage| are transferred to the decoded bytes.
  //
  // This method should be used after a read.
  template <typename FidlType>
  void Decode(internal::WireFormatVersion wire_format_version) {
    ZX_ASSERT(!is_transactional_);
    ZX_ASSERT(fidl::TypeTraits<FidlType>::kType != nullptr);
    Decode(wire_format_version, fidl::TypeTraits<FidlType>::kType,
           fidl::IsFidlTransactionalMessage<FidlType>::value);
  }

  // Decodes the message using |message_type| for the specified |wire_format_version|. If this
  // operation succeed, |status()| is ok and |bytes()| contains the decoded object.
  //
  // On success, the handles owned by |IncomingMessage| are transferred to the decoded bytes.
  //
  // This method should be used after a read.
  void Decode(internal::WireFormatVersion wire_format_version, const fidl_type_t* message_type,
              bool is_transactional);

  // Release the handle ownership after the message has been converted to its
  // decoded form. When used standalone and not as part of a |Decode|, this
  // method is only useful when interfacing with C APIs.
  void ReleaseHandles() { message_.num_handles = 0; }

  void MoveImpl(IncomingMessage&& other) noexcept {
    transport_vtable_ = other.transport_vtable_;
    message_ = other.message_;
    is_transactional_ = other.is_transactional_;
    other.ReleaseHandles();
  }

  // Decodes the message using |message_type|. If this operation succeed, |status()| is ok and
  // |bytes()| contains the decoded object.
  //
  // The first 16 bytes of the message must be the FIDL message header and are used for
  // determining the wire format version for decoding.
  //
  // On success, the handles owned by |IncomingMessage| are transferred to the decoded bytes.
  // If a buffer needs to be allocated during decode, |out_transformed_buffer| will contain that
  // buffer. This buffer will be stored on DecodedMessageBase and stays in scope for the lifetime
  // of the decoded message, which is responsible for freeing it.
  //
  // This method should be used after a read.
  void Decode(const fidl_type_t* message_type);

  // Performs basic transactional message header validation and sets the |fidl::Status| fields
  // accordingly.
  void ValidateHeader();

  const internal::TransportVTable* transport_vtable_ = nullptr;
  fidl_incoming_msg_t message_;
  bool is_transactional_ = false;
};

// Reads a transactional message from |transport| using the |bytes_storage| and
// |handles_storage| buffers as needed.
//
// Error information is embedded in the returned |IncomingMessage| in case of
// failures.
template <typename TransportObject>
IncomingMessage MessageRead(TransportObject&& transport, ::fidl::BufferSpan bytes_storage,
                            fidl_handle_t* handle_storage,
                            typename internal::AssociatedTransport<TransportObject>::HandleMetadata*
                                handle_metadata_storage,
                            uint32_t handle_capacity, const ReadOptions& options = {}) {
  auto type_erased_transport =
      internal::MakeAnyUnownedTransport(std::forward<TransportObject>(transport));
  uint32_t num_bytes, num_handles;
  zx_status_t status = type_erased_transport.read(
      options, bytes_storage.data, bytes_storage.capacity, handle_storage, handle_metadata_storage,
      handle_capacity, &num_bytes, &num_handles);
  if (status != ZX_OK) {
    return IncomingMessage::Create(fidl::Status::TransportError(status));
  }
  return IncomingMessage::Create(bytes_storage.data, num_bytes, handle_storage,
                                 handle_metadata_storage, num_handles);
}

namespace internal {

// DecodedMessageBase implements the common behavior to all
// |fidl::unstable::DecodedMessage<T>| subclasses. They may be created from an incoming
// message in encoded form, in which case they would perform the necessary
// decoding and own the decoded handles via RAII.
//
// |DecodedMessageBase| should never be instantiated directly. Rather, a
// subclass should be defined which adds the FIDL type-specific handle RAII
// behavior.
template <typename FidlType>
class DecodedMessageBase : public ::fidl::Status {
 public:
  // Creates an |DecodedMessageBase| by decoding the incoming message |msg|.
  // Consumes |msg|.
  //
  // The first 16 bytes of the message are assumed to be the FIDL message header and are used
  // for determining the wire format version for decoding.
  explicit DecodedMessageBase(::fidl::IncomingMessage&& msg) {
    static_assert(fidl::IsFidlTransactionalMessage<FidlType>::value);
    msg.Decode<FidlType>();
    bytes_ = msg.bytes();
    SetStatus(msg);
  }

  // Creates an |DecodedMessageBase| by decoding the incoming message |msg| as the specified
  // |wire_format_version|.
  // Consumes |msg|.
  explicit DecodedMessageBase(internal::WireFormatVersion wire_format_version,
                              ::fidl::IncomingMessage&& msg) {
    static_assert(!fidl::IsFidlTransactionalMessage<FidlType>::value);
    msg.Decode<FidlType>(wire_format_version);
    bytes_ = msg.bytes();
    SetStatus(msg);
  }

  // Creates an empty decoded message representing an error (e.g. failed to read
  // from a channel).
  //
  // |failure| must contain an error result.
  explicit DecodedMessageBase(const ::fidl::Status& failure) {
    ZX_DEBUG_ASSERT(!failure.ok());
    SetStatus(failure);
  }

 protected:
  DecodedMessageBase(const DecodedMessageBase&) = delete;
  DecodedMessageBase(DecodedMessageBase&&) = delete;
  DecodedMessageBase& operator=(const DecodedMessageBase&) = delete;
  DecodedMessageBase& operator=(DecodedMessageBase&&) = delete;

  ~DecodedMessageBase() = default;

  uint8_t* bytes() const { return bytes_; }

  void ResetBytes() { bytes_ = nullptr; }

 private:
  uint8_t* bytes_ = nullptr;
};

}  // namespace internal

// TODO(fxbug.dev/82681): Re-introduce stable APIs for standalone use of the
// FIDL wire format.
namespace unstable {

// This class manages the handles within |FidlType| and encodes the message automatically upon
// construction. Different from |OwnedEncodedMessage|, it takes in a caller-allocated buffer and
// uses that as the backing storage for the message. The buffer must outlive instances of this
// class.
template <typename FidlType, typename Transport = internal::ChannelTransport>
class UnownedEncodedMessage final {
 public:
  UnownedEncodedMessage(uint8_t* backing_buffer, uint32_t backing_buffer_size, FidlType* response)
      : UnownedEncodedMessage(Transport::kNumIovecs, backing_buffer, backing_buffer_size,
                              response) {}
  UnownedEncodedMessage(fidl::internal::WireFormatVersion wire_format_version,
                        uint8_t* backing_buffer, uint32_t backing_buffer_size, FidlType* response)
      : UnownedEncodedMessage(wire_format_version, Transport::kNumIovecs, backing_buffer,
                              backing_buffer_size, response) {}
  UnownedEncodedMessage(uint32_t iovec_capacity, uint8_t* backing_buffer,
                        uint32_t backing_buffer_size, FidlType* response)
      : UnownedEncodedMessage(fidl::internal::kLLCPPWireFormatVersion, iovec_capacity,
                              backing_buffer, backing_buffer_size, response) {}

  // Encodes |value| by allocating a backing buffer from |backing_buffer_allocator|.
  UnownedEncodedMessage(fidl::internal::AnyBufferAllocator& backing_buffer_allocator,
                        uint32_t backing_buffer_size, FidlType* value)
      : UnownedEncodedMessage(::fidl::internal::kLLCPPWireFormatVersion, Transport::kNumIovecs,
                              backing_buffer_allocator.TryAllocate(backing_buffer_size), value) {}

  // Encodes |value| using an existing |backing_buffer|.
  UnownedEncodedMessage(fidl::internal::WireFormatVersion wire_format_version,
                        uint32_t iovec_capacity, uint8_t* backing_buffer,
                        uint32_t backing_buffer_size, FidlType* value)
      : UnownedEncodedMessage(wire_format_version, iovec_capacity,
                              ::fitx::ok(::fidl::BufferSpan(backing_buffer, backing_buffer_size)),
                              value) {}

  // Core implementation which other constructors delegate to.
  UnownedEncodedMessage(::fidl::internal::WireFormatVersion wire_format_version,
                        uint32_t iovec_capacity,
                        ::fitx::result<::fidl::Error, ::fidl::BufferSpan> backing_buffer,
                        FidlType* value)
      : message_(backing_buffer.is_ok()
                     ? ::fidl::OutgoingMessage::Create_InternalMayBreak(
                           ::fidl::OutgoingMessage::InternalIovecConstructorArgs{
                               .transport_vtable = &Transport::VTable,
                               .iovecs = iovecs_,
                               .iovec_capacity = iovec_capacity,
                               .handles = handle_storage_.data(),
                               .handle_metadata = reinterpret_cast<fidl_handle_metadata_t*>(
                                   handle_metadata_storage_.data()),
                               .handle_capacity = kNumHandles,
                               .backing_buffer = backing_buffer->data,
                               .backing_buffer_capacity = backing_buffer->capacity,
                           })
                     : ::fidl::OutgoingMessage{backing_buffer.error_value()}),
        wire_format_version_(wire_format_version) {
    if (message_.ok()) {
      ZX_ASSERT(iovec_capacity <= std::size(iovecs_));
      message_.Encode<FidlType>(wire_format_version, value);
    }
  }

  UnownedEncodedMessage(const UnownedEncodedMessage&) = delete;
  UnownedEncodedMessage(UnownedEncodedMessage&&) = delete;
  UnownedEncodedMessage* operator=(const UnownedEncodedMessage&) = delete;
  UnownedEncodedMessage* operator=(UnownedEncodedMessage&&) = delete;

  zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
  const char* status_string() const { return message_.status_string(); }
#endif
  bool ok() const { return message_.status() == ZX_OK; }
  std::string FormatDescription() const { return message_.FormatDescription(); }
  const char* lossy_description() const { return message_.lossy_description(); }
  const ::fidl::Status& error() const { return message_.error(); }

  ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_; }

  ::fidl::WireFormatMetadata wire_format_metadata() const {
    return fidl::internal::WireFormatMetadataForVersion(wire_format_version_);
  }

  template <typename TransportObject>
  void Write(TransportObject&& client, WriteOptions options = {}) {
    message_.Write(std::forward<TransportObject>(client), std::move(options));
  }

 private:
  static constexpr uint32_t kNumHandles =
      fidl::internal::ClampedHandleCount<FidlType, fidl::MessageDirection::kSending>();
  std::array<zx_handle_t, kNumHandles> handle_storage_;
  std::array<typename Transport::HandleMetadata, kNumHandles> handle_metadata_storage_;
  zx_channel_iovec_t iovecs_[Transport::kNumIovecs];
  fidl::OutgoingMessage message_;
  fidl::internal::WireFormatVersion wire_format_version_;
};

// This class owns a message of |FidlType| and encodes the message automatically upon construction
// into a byte buffer.
template <typename FidlType, typename Transport = internal::ChannelTransport>
class OwnedEncodedMessage final {
 public:
  explicit OwnedEncodedMessage(FidlType* response)
      : message_(1u, backing_buffer_.data(), static_cast<uint32_t>(backing_buffer_.size()),
                 response) {}
  explicit OwnedEncodedMessage(fidl::internal::WireFormatVersion wire_format_version,
                               FidlType* response)
      : message_(wire_format_version, 1u, backing_buffer_.data(),
                 static_cast<uint32_t>(backing_buffer_.size()), response) {}
  // Internal constructor.
  explicit OwnedEncodedMessage(::fidl::internal::AllowUnownedInputRef allow_unowned,
                               FidlType* response)
      : message_(Transport::kNumIovecs, backing_buffer_.data(),
                 static_cast<uint32_t>(backing_buffer_.size()), response) {}
  explicit OwnedEncodedMessage(::fidl::internal::AllowUnownedInputRef allow_unowned,
                               fidl::internal::WireFormatVersion wire_format_version,
                               FidlType* response)
      : message_(wire_format_version, Transport::kNumIovecs, backing_buffer_.data(),
                 static_cast<uint32_t>(backing_buffer_.size()), response) {}
  OwnedEncodedMessage(const OwnedEncodedMessage&) = delete;
  OwnedEncodedMessage(OwnedEncodedMessage&&) = delete;
  OwnedEncodedMessage* operator=(const OwnedEncodedMessage&) = delete;
  OwnedEncodedMessage* operator=(OwnedEncodedMessage&&) = delete;

  zx_status_t status() const { return message_.status(); }
#ifdef __Fuchsia__
  const char* status_string() const { return message_.status_string(); }
#endif
  bool ok() const { return message_.ok(); }
  std::string FormatDescription() const { return message_.FormatDescription(); }
  const char* lossy_description() const { return message_.lossy_description(); }
  const ::fidl::Status& error() const { return message_.error(); }

  ::fidl::OutgoingMessage& GetOutgoingMessage() { return message_.GetOutgoingMessage(); }

  template <typename TransportObject>
  void Write(TransportObject&& client, WriteOptions options = {}) {
    message_.Write(std::forward<TransportObject>(client), std::move(options));
  }

  ::fidl::WireFormatMetadata wire_format_metadata() const {
    return message_.wire_format_metadata();
  }

 private:
  ::fidl::internal::OutgoingMessageBuffer<FidlType> backing_buffer_;
  ::fidl::unstable::UnownedEncodedMessage<FidlType, Transport> message_;
};

// This class manages the handles within |FidlType| and decodes the message automatically upon
// construction. It always borrows external buffers for the backing storage of the message.
// This class should mostly be used for tests.
template <typename FidlType, typename Transport = internal::ChannelTransport,
          typename Enable = void>
class DecodedMessage;

// Specialization for transactional messages.
template <typename FidlType, typename Transport>
class DecodedMessage<FidlType, Transport,
                     std::void_t<decltype(fidl::TypeTraits<FidlType>::kMessageKind)>>
    final : public ::fidl::internal::DecodedMessageBase<FidlType> {
  using Base = ::fidl::internal::DecodedMessageBase<FidlType>;

 public:
  using Base::DecodedMessageBase;

  DecodedMessage(uint8_t* bytes, uint32_t byte_actual, zx_handle_t* handles = nullptr,
                 typename Transport::HandleMetadata* handle_metadata = nullptr,
                 uint32_t handle_actual = 0)
      : Base(::fidl::IncomingMessage::Create(bytes, byte_actual, handles, handle_metadata,
                                             handle_actual)) {}

  ~DecodedMessage() {
    if constexpr (::fidl::IsResource<FidlType>::value) {
      if (Base::ok() && (PrimaryObject() != nullptr)) {
        PrimaryObject()->_CloseHandles();
      }
    }
  }

  FidlType* PrimaryObject() {
    ZX_DEBUG_ASSERT(Base::ok());
    return reinterpret_cast<FidlType*>(Base::bytes());
  }

  // Release the ownership of the decoded message. That means that the handles won't be closed
  // When the object is destroyed.
  // After calling this method, the |DecodedMessage| object should not be used anymore.
  void ReleasePrimaryObject() { ::fidl::internal::DecodedMessageBase<FidlType>::ResetBytes(); }
};

// Specialization for non-transactional types (tables, structs, unions).
template <typename FidlType, typename Transport>
class DecodedMessage<FidlType, Transport,
                     std::enable_if_t<::fidl::IsFidlObject<FidlType>::value, void>>
    final : public ::fidl::internal::DecodedMessageBase<FidlType> {
  using Base = ::fidl::internal::DecodedMessageBase<FidlType>;

 public:
  using Base::DecodedMessageBase;

  DecodedMessage(uint8_t* bytes, uint32_t byte_actual, zx_handle_t* handles = nullptr,
                 typename Transport::HandleMetadata* handle_metadata = nullptr,
                 uint32_t handle_actual = 0)
      : Base(::fidl::internal::WireFormatVersion::kV2,
             ::fidl::IncomingMessage::Create(
                 bytes, byte_actual, handles, handle_metadata, handle_actual,
                 ::fidl::IncomingMessage::kSkipMessageHeaderValidation)) {}

  // Internal constructor for specifying a specific wire format version.
  DecodedMessage(::fidl::internal::WireFormatVersion wire_format_version, uint8_t* bytes,
                 uint32_t byte_actual, zx_handle_t* handles = nullptr,
                 typename Transport::HandleMetadata* handle_metadata = nullptr,
                 uint32_t handle_actual = 0)
      : Base(wire_format_version, ::fidl::IncomingMessage::Create(
                                      bytes, byte_actual, handles, handle_metadata, handle_actual,
                                      ::fidl::IncomingMessage::kSkipMessageHeaderValidation)) {}

  explicit DecodedMessage(const fidl_incoming_msg_t* c_msg)
      : DecodedMessage(static_cast<uint8_t*>(c_msg->bytes), c_msg->num_bytes, c_msg->handles,
                       reinterpret_cast<fidl_channel_handle_metadata_t*>(c_msg->handle_metadata),
                       c_msg->num_handles) {}

  // Internal constructor for specifying a specific wire format version.
  DecodedMessage(::fidl::internal::WireFormatVersion wire_format_version,
                 const fidl_incoming_msg_t* c_msg)
      : DecodedMessage(wire_format_version, static_cast<uint8_t*>(c_msg->bytes), c_msg->num_bytes,
                       c_msg->handles,
                       reinterpret_cast<fidl_channel_handle_metadata_t*>(c_msg->handle_metadata),
                       c_msg->num_handles) {}

  ~DecodedMessage() {
    if constexpr (::fidl::IsResource<FidlType>::value) {
      if (Base::ok() && (PrimaryObject() != nullptr)) {
        PrimaryObject()->_CloseHandles();
      }
    }
  }

  FidlType* PrimaryObject() {
    ZX_DEBUG_ASSERT(Base::ok());
    return reinterpret_cast<FidlType*>(Base::bytes());
  }

  // Release the ownership of the decoded message. That means that the handles won't be closed
  // When the object is destroyed.
  // After calling this method, the |DecodedMessage| object should not be used anymore.
  void ReleasePrimaryObject() { Base::ResetBytes(); }
};

}  // namespace unstable

// Holds the result of converting an outgoing message to an incoming message.
//
// |OutgoingToIncomingMessage| objects own the bytes and handles resulting from
// conversion.
class OutgoingToIncomingMessage {
 public:
  // Converts an outgoing message to an incoming message.
  //
  // In doing so, it will make syscalls to fetch rights and type information
  // of any provided handles. The caller is responsible for ensuring that
  // returned handle rights and object types are checked appropriately.
  //
  // The constructed |OutgoingToIncomingMessage| will take ownership over
  // handles from the input |OutgoingMessage|.
  explicit OutgoingToIncomingMessage(OutgoingMessage& input);

  ~OutgoingToIncomingMessage() = default;

  fidl::IncomingMessage& incoming_message() & {
    ZX_DEBUG_ASSERT(ok());
    return incoming_message_;
  }

  [[nodiscard]] zx_status_t status() const { return incoming_message_.status(); }
  [[nodiscard]] bool ok() const { return incoming_message_.ok(); }
  [[nodiscard]] std::string FormatDescription() const;

 private:
  static fidl::IncomingMessage ConversionImpl(
      OutgoingMessage& input, OutgoingMessage::CopiedBytes& buf_bytes,
      std::unique_ptr<zx_handle_t[]>& buf_handles,
      std::unique_ptr<fidl_channel_handle_metadata_t[]>& buf_handle_metadata);

  OutgoingMessage::CopiedBytes buf_bytes_;
  std::unique_ptr<zx_handle_t[]> buf_handles_ = {};
  std::unique_ptr<fidl_channel_handle_metadata_t[]> buf_handle_metadata_ = {};
  fidl::IncomingMessage incoming_message_;
};

}  // namespace fidl

#endif  // LIB_FIDL_LLCPP_MESSAGE_H_
