// 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.

#ifndef SRC_SYS_FUZZING_COMMON_INPUT_H_
#define SRC_SYS_FUZZING_COMMON_INPUT_H_

#include <fuchsia/fuzzer/cpp/fidl.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>

#include "src/lib/fxl/macros.h"
#include "src/sys/fuzzing/common/shared-memory.h"

namespace fuzzing {

using FidlInput = ::fuchsia::fuzzer::Input;

// Represents a single fuzzing input. A corpus is a collection of fuzzing inputs. Inputs are either
// provided as part of a seed corpus, or generated by mutating existing inputs.
class Input final {
 public:
  Input() = default;
  Input(const std::initializer_list<uint8_t>& bytes) : Input(std::vector<uint8_t>(bytes)) {}
  explicit Input(const std::vector<uint8_t>& bytes) : Input(bytes.data(), bytes.size()) {}
  explicit Input(const std::string& bytes) : Input(bytes.c_str(), bytes.size()) {}
  explicit Input(SharedMemory& shmem) : Input(shmem.data(), shmem.size()) {}
  Input(Input&& other) noexcept { *this = std::move(other); }

  ~Input() = default;

  Input& operator=(Input&& other) noexcept;
  bool operator==(const Input& other) const;
  bool operator!=(const Input& other) const { return !(*this == other); }

  const uint8_t* data() const { return data_.get(); }
  uint8_t* data() { return data_.get(); }
  size_t size() const { return size_; }
  size_t capacity() const { return capacity_; }
  size_t num_features() const { return num_features_; }

  void set_num_features(size_t num_features) { num_features_ = num_features; }

  // Returns a hex string representation. Mostly used for testing/debugging.
  std::string ToHex() const;

  // Exchanges the internal state of this input with another.
  void Swap(Input& other);

  // Creates a copy of this input.
  Input Duplicate() const;

  // Ensures the input has at least the given |capacity|.
  void Reserve(size_t capacity);

  // Appends data to this input. The input must have sufficient remaining capacity for |size| bytes.
  void Write(const void* data, size_t size);
  void Write(uint8_t one_byte);

  // Reserves capacity and sets the size of this input to |size| bytes. This method does NOT
  // initialize the data, but can be used in conjunction with the |data()| accessor to write into
  // the input. Returns the new size.
  size_t Resize(size_t size);

  // Truncates the input if larger than |max_size|. Returns the new size.
  size_t Truncate(size_t max_size);

  // Reduces the capacity of this input to its size. Returns the new size.
  size_t ShrinkToFit();

  // Removes all data from this input.
  void Clear();

 private:
  Input(const void* data, size_t size) { Allocate(size, data, size); }

  void Allocate(size_t capacity, const void* data = nullptr, size_t size = 0);

  void StartExport(zx::socket* sender, FidlInput* receiver) const;
  void FinishExport(const zx::socket& sender) const;

  std::unique_ptr<uint8_t[]> data_;
  size_t capacity_ = 0;
  size_t size_ = 0;
  size_t num_features_ = 0;

  FXL_DISALLOW_COPY_AND_ASSIGN(Input);
};

}  // namespace fuzzing

#endif  // SRC_SYS_FUZZING_COMMON_INPUT_H_
