// Copyright 2020 the V8 project 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 V8_SNAPSHOT_SNAPSHOT_DATA_H_
#define V8_SNAPSHOT_SNAPSHOT_DATA_H_

#include "src/base/bit-field.h"
#include "src/base/memory.h"
#include "src/codegen/external-reference-table.h"
#include "src/utils/memcopy.h"
#include "src/utils/vector.h"

namespace v8 {
namespace internal {

// Forward declarations.
class Isolate;
class Serializer;

class SerializedData {
 public:
  SerializedData(byte* data, int size)
      : data_(data), size_(size), owns_data_(false) {}
  SerializedData() : data_(nullptr), size_(0), owns_data_(false) {}
  SerializedData(SerializedData&& other) V8_NOEXCEPT
      : data_(other.data_),
        size_(other.size_),
        owns_data_(other.owns_data_) {
    // Ensure |other| will not attempt to destroy our data in destructor.
    other.owns_data_ = false;
  }
  SerializedData(const SerializedData&) = delete;
  SerializedData& operator=(const SerializedData&) = delete;

  virtual ~SerializedData() {
    if (owns_data_) DeleteArray<byte>(data_);
  }

  uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }

  using ChunkSizeBits = base::BitField<uint32_t, 0, 31>;
  using IsLastChunkBits = base::BitField<bool, 31, 1>;

  static constexpr uint32_t kMagicNumberOffset = 0;
  static constexpr uint32_t kMagicNumber =
      0xC0DE0000 ^ ExternalReferenceTable::kSize;

 protected:
  void SetHeaderValue(uint32_t offset, uint32_t value) {
    base::WriteLittleEndianValue(reinterpret_cast<Address>(data_) + offset,
                                 value);
  }

  uint32_t GetHeaderValue(uint32_t offset) const {
    return base::ReadLittleEndianValue<uint32_t>(
        reinterpret_cast<Address>(data_) + offset);
  }

  void AllocateData(uint32_t size);

  void SetMagicNumber() { SetHeaderValue(kMagicNumberOffset, kMagicNumber); }

  byte* data_;
  uint32_t size_;
  bool owns_data_;
};

// Wrapper around reservation sizes and the serialization payload.
class V8_EXPORT_PRIVATE SnapshotData : public SerializedData {
 public:
  // Used when producing.
  explicit SnapshotData(const Serializer* serializer);

  // Used when consuming.
  explicit SnapshotData(const Vector<const byte> snapshot)
      : SerializedData(const_cast<byte*>(snapshot.begin()), snapshot.length()) {
  }

  virtual Vector<const byte> Payload() const;

  Vector<const byte> RawData() const {
    return Vector<const byte>(data_, size_);
  }

 protected:
  // Empty constructor used by SnapshotCompression so it can manually allocate
  // memory.
  SnapshotData() : SerializedData() {}
  friend class SnapshotCompression;

  // Resize used by SnapshotCompression so it can shrink the compressed
  // SnapshotData.
  void Resize(uint32_t size) { size_ = size; }

  // The data header consists of uint32_t-sized entries:
  // [0] magic number and (internal) external reference count
  // [1] payload length
  // ... serialized payload
  static const uint32_t kPayloadLengthOffset = kMagicNumberOffset + kUInt32Size;
  static const uint32_t kHeaderSize = kPayloadLengthOffset + kUInt32Size;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_SNAPSHOT_DATA_H_
