// Copyright 2018 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_CPP_DECODER_H_
#define LIB_FIDL_CPP_DECODER_H_

#include <lib/fidl/cpp/message.h>
#include <zircon/fidl.h>

#ifdef __Fuchsia__
#include <lib/zx/handle.h>
#include <lib/zx/object.h>
#endif

namespace fidl {

class Decoder final {
 public:
  explicit Decoder(HLCPPIncomingMessage message);
  explicit Decoder(HLCPPIncomingBody body);
  ~Decoder();

  template <typename T>
  T* GetPtr(size_t offset) {
    return reinterpret_cast<T*>((body_.bytes().data() - body_offset_) + offset);
  }

  size_t GetOffset(const void* ptr) const { return GetOffset(reinterpret_cast<uintptr_t>(ptr)); }
  size_t GetOffset(uintptr_t ptr) const {
    // The |ptr| value comes from the message buffer, which we've already
    // validated. That means it should correspond to a valid offset within the
    // message.
    return ptr - reinterpret_cast<uintptr_t>(body_.bytes().data() - body_offset_);
  }

#ifdef __Fuchsia__
  void DecodeHandle(zx::object_base* value, size_t offset) {
    zx_handle_t* handle = GetPtr<zx_handle_t>(offset);
    value->reset(*handle);
    *handle = ZX_HANDLE_INVALID;
    if (value->is_valid()) {
      ++handle_index_;
    }
  }

  zx::handle ClaimUnknownHandle() {
    return zx::handle(body_.handles().data()[handle_index_++].handle);
  }

  void CloseUnknownHandlesInEnvelope(const fidl_envelope_v2_t* envelope) {
    EnvelopeUnknownDataInfoResult info = EnvelopeUnknownDataInfo(envelope);
    for (uint32_t i = 0; i < info.num_handles; i++) {
      ClaimUnknownHandle();
    }
  }
#endif

  size_t EnvelopeValueOffset(const fidl_envelope_v2_t* envelope) const {
    if ((envelope->flags & FIDL_ENVELOPE_FLAGS_INLINING_MASK) != 0) {
      return GetOffset(&envelope->inline_value);
    }
    return GetOffset(*reinterpret_cast<const void* const*>(envelope));
  }

  struct EnvelopeUnknownDataInfoResult {
    size_t value_offset;
    uint32_t num_bytes;
    uint16_t num_handles;
    uint16_t flags;
  };

  EnvelopeUnknownDataInfoResult EnvelopeUnknownDataInfo(const fidl_envelope_v2_t* envelope) const {
    const auto* unknown_data_envelope =
        reinterpret_cast<const fidl_envelope_v2_unknown_data_t*>(envelope);

    EnvelopeUnknownDataInfoResult result;
    if ((unknown_data_envelope->flags & FIDL_ENVELOPE_FLAGS_INLINING_MASK) != 0) {
      result.value_offset = GetOffset(&envelope->inline_value);
      result.num_bytes = 4;
    } else {
      result.value_offset = unknown_data_envelope->out_of_line.offset;
      result.num_bytes = unknown_data_envelope->out_of_line.num_bytes;
    }
    result.num_handles = unknown_data_envelope->num_handles;
    result.flags = unknown_data_envelope->flags;

    return result;
  }

 private:
  HLCPPIncomingBody body_;

  // The body_offset_ is either 16 (when decoding the body of a transactional message, which is
  // itself a concatenation of 2 FIDL messages, the header and body), or 0 (when decoding a
  // standalone "at-rest" message body).
  uint32_t body_offset_ = 0;
#ifdef __Fuchsia__
  uint32_t handle_index_ = 0;
#endif
};

}  // namespace fidl

#endif  // LIB_FIDL_CPP_DECODER_H_
