// Copyright 2021 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 <lib/fidl/cpp/wire_format_metadata.h>
#include <zircon/assert.h>

#include <cstring>

namespace fidl {

WireFormatMetadata WireFormatMetadata::FromOpaque(fidl_opaque_wire_format_metadata_t opaque) {
  uint8_t bytes[8] = {};
  memcpy(bytes, &opaque, sizeof(opaque));
  WireFormatMetadata metadata;
  metadata.disambiguator_ = bytes[0];
  metadata.magic_number_ = bytes[1];
  metadata.at_rest_flags_[0] = bytes[2];
  metadata.at_rest_flags_[1] = bytes[3];
  metadata.reserved_[0] = bytes[4];
  metadata.reserved_[1] = bytes[5];
  metadata.reserved_[2] = bytes[6];
  metadata.reserved_[3] = bytes[7];
  return metadata;
}

WireFormatMetadata WireFormatMetadata::FromTransactionalHeader(fidl_message_header_t header) {
  WireFormatMetadata metadata;
  metadata.disambiguator_ = 0;
  metadata.magic_number_ = header.magic_number;
  // See
  // https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0138_handling_unknown_interactions?hl=en#transactional-message-header-v4
  //
  // At-rest flags come first, followed by dynamic flags.
  //
  // Note: the V1, V2, and "V2 after unknown interactions" FIDL wire formats all
  // store the at_rest flags in the same location. When a future FIDL revision
  // change the location of the at_rest flags, this would need to be updated to
  // be conditional on the magic number.
  metadata.at_rest_flags_[0] = header.at_rest_flags[0];
  metadata.at_rest_flags_[1] = header.at_rest_flags[1];
  memset(metadata.reserved_, 0, sizeof(metadata.reserved_));
  return metadata;
}

fidl_opaque_wire_format_metadata_t WireFormatMetadata::ToOpaque() const {
  // Translate the metadata to a binary representation.
  // We could use a for-loop or fancier serialization, but an array gives the
  // most explicit control over the ABI.
  uint8_t bytes[8] = {
      disambiguator_, magic_number_, at_rest_flags_[0], at_rest_flags_[1],
      reserved_[0],   reserved_[1],  reserved_[2],      reserved_[3],
  };
  uint64_t opaque;
  static_assert(sizeof(opaque) == sizeof(bytes), "Opaque metadata is 8 bytes");
  memcpy(&opaque, bytes, sizeof(opaque));
  return fidl_opaque_wire_format_metadata_t{opaque};
}

bool WireFormatMetadata::is_valid() const {
  // Note: this method should be in sync with |fidl_validate_txn_header|.
  // TODO(fxbug.dev/88366): Support the upcoming wire format magic in RFC-0138.
  return magic_number_ == kFidlWireFormatMagicNumberInitial;
}

internal::WireFormatVersion WireFormatMetadata::wire_format_version() const {
  ZX_ASSERT_MSG(is_valid(), "Invalid metadata %d %d %d", at_rest_flags_[0], at_rest_flags_[1],
                magic_number_);
  if ((at_rest_flags_[0] & FIDL_MESSAGE_HEADER_AT_REST_FLAGS_0_USE_VERSION_V2) == 0) {
    return internal::WireFormatVersion::kV1;
  }
  return internal::WireFormatVersion::kV2;
}

::FidlWireFormatVersion WireFormatMetadata::c_wire_format_version() const {
  switch (wire_format_version()) {
    case internal::WireFormatVersion::kV1:
      return FIDL_WIRE_FORMAT_VERSION_V1;
    case internal::WireFormatVersion::kV2:
      return FIDL_WIRE_FORMAT_VERSION_V2;
  }
  ZX_PANIC("Unsupported wire format version %d", static_cast<int>(wire_format_version()));
}

namespace internal {

// Constructs a |WireFormatMetadata| corresponding to the version.
WireFormatMetadata WireFormatMetadataForVersion(WireFormatVersion version) {
  WireFormatMetadata metadata;
  metadata.magic_number_ = kFidlWireFormatMagicNumberInitial;
  switch (version) {
    case WireFormatVersion::kV1:
      return metadata;
    case WireFormatVersion::kV2:
      metadata.at_rest_flags_[0] = FIDL_MESSAGE_HEADER_AT_REST_FLAGS_0_USE_VERSION_V2;
      return metadata;
  }
  ZX_PANIC("Unsupported wire format version %d", static_cast<int>(version));
}

}  // namespace internal
}  // namespace fidl
