// 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_MESSAGE_PART_H_
#define LIB_FIDL_CPP_MESSAGE_PART_H_

#include <lib/fidl/internal.h>
#include <stdint.h>
#include <string.h>
#include <zircon/types.h>

namespace fidl {

// Part of a FIDL message.
//
// A FIDL message has two parts: the bytes and the handles. This class is used
// to represent both kinds of parts.
//
// Each part of the message has a data buffer, which contains the actual data
// for that part of the message, a capacity for that buffer, and the actual
// amount of data stored in the buffer, which might be less that the capacity if
// the buffer is not completely full.
template <typename T>
class MessagePart {
 public:
  using value_type = T;
  using const_iterator = const T*;

  // A message part with no storage.
  MessagePart() : data_(nullptr), capacity_(0u), actual_(0u) {}

  // A message part that uses the given storage.
  //
  // The constructed |MessagePart| object does not take ownership of the given
  // storage.
  MessagePart(T* data, uint32_t capacity, uint32_t actual = 0u)
      : data_(data), capacity_(capacity), actual_(actual) {}

  // The copy constructor is deleted because a MessagePart may own handles (see
  // HandlePart/HandleDispositionPart/HandleInfoPart below), which may not be copied.
  MessagePart(const MessagePart& other) = delete;
  MessagePart& operator=(const MessagePart& other) = delete;

  MessagePart(MessagePart&& other)
      : data_(other.data_), capacity_(other.capacity_), actual_(other.actual_) {
    other.data_ = nullptr;
    other.capacity_ = 0u;
    other.actual_ = 0u;
  }

  // A copy constructor for |other|, which trims the first |pos| number of |T|s from it when
  // copying.  This should not be invoked on any |Handle*Part| specialization of the |MessagePart|
  // class, as handle containing classes may not be copied (handles must be unique).
  MessagePart(const MessagePart& other, uint32_t pos)
      : data_(other.data_ + (pos * sizeof(T))),
        capacity_(other.capacity_ > pos * sizeof(T) ? other.capacity_ - (pos * sizeof(T)) : 0),
        actual_(other.actual_ > pos * sizeof(T) ? other.actual_ - (pos * sizeof(T)) : 0) {
    static_assert(
        !(std::is_same<zx_handle_t, T>::value || std::is_same<zx_handle_disposition_t, T>::value ||
          std::is_same<zx_handle_info_t, T>::value),
        "Handle holding containers may not be copied");
  }

  MessagePart& operator=(MessagePart&& other) {
    if (this == &other)
      return *this;
    data_ = other.data_;
    capacity_ = other.capacity_;
    actual_ = other.actual_;
    other.data_ = nullptr;
    other.capacity_ = 0u;
    other.actual_ = 0u;
    return *this;
  }

  // Constructs a full |MessagePart| wrapping an array.
  // The array is assumed to be initialized with data, such that |actual()|
  // will match exactly the length of the array.
  template <size_t N>
  static MessagePart WrapFull(T (&array)[N]) {
    return MessagePart(array, N, N);
  }

  // Constructs an empty |MessagePart| wrapping an array.
  // The array is assumed to be uninitialized, hence |actual()| is set to 0.
  template <size_t N>
  static MessagePart WrapEmpty(T (&array)[N]) {
    return MessagePart(array, N, 0);
  }

  // The data stored in this part of the message.
  T* data() const { return data_; }

  // The total amount of storage available for this part of the message.
  //
  // This part of the message might not actually use all of this storage. To
  // determine how much storage is actually being used, see |actual()|.
  uint32_t capacity() const { return capacity_; }

  // The amount of storage that is actually being used for this part of the
  // message.
  //
  // There might be more storage available than is actually being used. To
  // determine how much storage is available, see |capacity()|.
  uint32_t actual() const { return actual_; }
  void set_actual(uint32_t actual) { actual_ = actual; }

  T* begin() { return data_; }
  const T* begin() const { return data_; }
  const T* cbegin() const { return data_; }

  T* end() { return data_ + actual_; }
  const T* end() const { return data_ + actual_; }
  const T* cend() const { return data_ + actual_; }

  size_t size() const { return actual_; }

 private:
  T* data_;
  uint32_t capacity_;
  uint32_t actual_;
};

using BytePart = MessagePart<uint8_t>;
using HandlePart = MessagePart<zx_handle_t>;
using HandleDispositionPart = MessagePart<zx_handle_disposition_t>;
using HandleInfoPart = MessagePart<zx_handle_info_t>;

}  // namespace fidl

#endif  // LIB_FIDL_CPP_MESSAGE_PART_H_
