// Copyright 2017 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 SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_PACKET_VIEW_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_PACKET_VIEW_H_

#include <zircon/assert.h>

#include <cstdint>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"

namespace bt {

// Base class-template for generic packets that contain a header and a payload.
// A PacketView is a light-weight object that operates over a previously
// allocated ByteBuffer without taking ownership of it. The PacketView
// class-template provides a read-only view over the underlying buffer while
// MutablePacketView allows modification of the underlying buffer.
//
// Example usage:
//
//   // Allocate a buffer
//   StaticByteBuffer<512> buffer;
//
//   // Receive some data on the buffer.
//   foo::WriteMyPacket(buffer.mutable_data(), ...);
//
//   // Read packet header contents:
//   struct MyHeaderType {
//     uint8_t field0;
//   };
//
//   PacketView<MyHeaderType> packet(&buffer, 0);
//   std::cout << "My header field is: " << packet.header().field0;
//
//   // If the packet has an expected payload size, pass that into the
//   // constructor:
//   struct MyPayloadType {
//     uint8_t byte_field;
//     uint16_t uint16_field;
//     uint8_t array_field[];
//   } __PACKED;
//
//   MutablePacketView<MyHeaderType> packet(&buffer, sizeof(MyPayloadType) + 2);
//   packet.mutable_payload<MyPayloadType>().byte_field = 0xFF;
//   packet.mutable_payload<MyPayloadType>().uint16_field = 0xFFFF;
//   packet.mutable_payload<MyPayloadType>().array_field[0] = 0x00;
//   packet.mutable_payload<MyPayloadType>().array_field[1] = 0x01;
//
// MutablePacketView allows itself to be resized at any time. This is useful
// when the complete packet payload is unknown prior to reading the header
// contents. For example:
//
//   MutablePacketView<MyHeaderType view(&buffer, my_max_payload_length);
//   view.mutable_data().Write(data);
//   view.Resize(view.header().payload_size);
template <typename HeaderType>
class PacketView {
 public:
  // The default constructor initializes an empty packet view. This is to enable
  // PacketView to be used by value in structures and stl containers.
  PacketView() : buffer_(nullptr), size_(0u) {}

  // Initializes this Packet to operate over |buffer|. |payload_size| is the
  // size of the packet payload not including the packet header. A
  // |payload_size| value of 0 indicates that the packet contains no payload.
  explicit PacketView(const ByteBuffer* buffer, size_t payload_size = 0u)
      : buffer_(buffer), size_(sizeof(HeaderType) + payload_size) {
    ZX_ASSERT(buffer_);
    ZX_ASSERT_MSG(buffer_->size() >= size_, "view size %zu exceeds buffer size %zu", size_,
                  buffer_->size());
  }

  const BufferView data() const { return buffer_->view(0, size_); }
  const BufferView payload_data() const {
    return buffer_->view(sizeof(HeaderType), size_ - sizeof(HeaderType));
  }

  size_t size() const { return size_; }
  size_t payload_size() const { return size() - sizeof(HeaderType); }

  const uint8_t* payload_bytes() const {
    ZX_ASSERT(is_valid());
    return payload_size() ? buffer_->data() + sizeof(HeaderType) : nullptr;
  }

  const HeaderType& header() const {
    ZX_ASSERT(is_valid());
    return *reinterpret_cast<const HeaderType*>(buffer_->data());
  }

  template <typename PayloadType>
  const PayloadType& payload() const {
    ZX_ASSERT(sizeof(PayloadType) <= payload_size());
    return *reinterpret_cast<const PayloadType*>(payload_bytes());
  }

  // A PacketView that contains no backing buffer is considered invalid. A
  // PacketView that was initialized with a buffer that is too small is invalid.
  bool is_valid() const { return buffer_ && size_ >= sizeof(HeaderType); }

  // Adjusts the size of this PacketView to match the given |payload_size|. This
  // is useful when the exact packet size is not known during construction.
  //
  // This performs runtime checks to make sure that the underlying buffer is
  // approriately sized.
  void Resize(size_t payload_size) { this->set_size(sizeof(HeaderType) + payload_size); }

 protected:
  void set_size(size_t size) {
    ZX_ASSERT(buffer_);
    ZX_ASSERT(buffer_->size() >= size);
    ZX_ASSERT(size >= sizeof(HeaderType));
    size_ = size;
  }

  const ByteBuffer* buffer() const { return buffer_; }

 private:
  const ByteBuffer* buffer_;  // weak
  size_t size_;
};

template <typename HeaderType>
class MutablePacketView : public PacketView<HeaderType> {
 public:
  MutablePacketView() = default;

  explicit MutablePacketView(MutableByteBuffer* buffer, size_t payload_size = 0u)
      : PacketView<HeaderType>(buffer, payload_size) {}

  MutableBufferView mutable_data() { return mutable_buffer()->mutable_view(0, this->size()); }

  MutableBufferView mutable_payload_data() const {
    return mutable_buffer()->mutable_view(sizeof(HeaderType), this->size() - sizeof(HeaderType));
  }

  uint8_t* mutable_payload_bytes() {
    return this->payload_size() ? mutable_buffer()->mutable_data() + sizeof(HeaderType) : nullptr;
  }

  HeaderType* mutable_header() {
    return reinterpret_cast<HeaderType*>(mutable_buffer()->mutable_data());
  }

  template <typename PayloadType>
  PayloadType* mutable_payload() {
    ZX_ASSERT(sizeof(PayloadType) <= this->payload_size());
    return reinterpret_cast<PayloadType*>(mutable_payload_bytes());
  }

 private:
  MutableByteBuffer* mutable_buffer() const {
    // Cast-away the const. This is OK in this case since we're storing our
    // buffer in the parent class instead of duplicating a non-const version in
    // this class.
    return const_cast<MutableByteBuffer*>(static_cast<const MutableByteBuffer*>(this->buffer()));
  }
};

}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_PACKET_VIEW_H_
