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

// Benchmarks for a reference encoder / decoder specialized to ByteVector,
// as defined in the FIDL benchmark suite.

#include <cstdint>

#include "builder.h"
#include "decode_benchmark_util.h"
#include "encode_benchmark_util.h"
#include "util.h"

namespace {

template <size_t StackBufferSize>
bool EncodeByteVector(void* value, const char** error,
                      fit::function<void(const uint8_t*, size_t)> callback) {
  fidl_vector_t* vec = reinterpret_cast<fidl_vector_t*>(value);

  size_t count = CLEAR_COUNT_OWNERSHIP_BIT(vec->count);
  size_t aligned_size = FIDL_ALIGN(count);
  size_t needed_buffer_size = aligned_size + sizeof(fidl_vector_t);

  uint8_t buf[StackBufferSize];

  *reinterpret_cast<fidl_vector_t*>(buf) = fidl_vector_t{
      .count = count,
      .data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT),
  };
  if (count != 0) {
    if (vec->data == nullptr) {
      *error = "vector with null data had non-zero element count";
      return false;
    }
    // Zero the last 8 bytes which pad the end of the out of line block.
    *reinterpret_cast<uint64_t*>(reinterpret_cast<uintptr_t>(buf) + needed_buffer_size - 8) = 0;
    memcpy(buf + sizeof(fidl_vector_t), vec->data, aligned_size);
  }

  callback(buf, needed_buffer_size);
  return true;
}

bool DecodeByteVector(uint8_t* bytes, size_t bytes_size, zx_handle_t* handles, size_t handles_size,
                      const char** error) {
  if (handles_size != 0) {
    *error = "no handles expected";
    return false;
  }

  fidl_vector_t* vec = reinterpret_cast<fidl_vector_t*>(bytes);
  if (unlikely(reinterpret_cast<uintptr_t>(vec->data) != FIDL_ALLOC_PRESENT)) {
    *error = "non-nullable vector missing out of line data";
    return false;
  }
  vec->data = bytes + sizeof(fidl_vector_t);
  return true;
}

bool BenchmarkEncodeByteVector16(perftest::RepeatState* state) {
  return encode_benchmark_util::EncodeBenchmark(state, benchmark_suite::Build_ByteVector_16,
                                                EncodeByteVector<32>);
}
bool BenchmarkEncodeByteVector256(perftest::RepeatState* state) {
  return encode_benchmark_util::EncodeBenchmark(state, benchmark_suite::Build_ByteVector_256,
                                                EncodeByteVector<272>);
}
bool BenchmarkEncodeByteVector4096(perftest::RepeatState* state) {
  return encode_benchmark_util::EncodeBenchmark(state, benchmark_suite::Build_ByteVector_4096,
                                                EncodeByteVector<4112>);
}
bool BenchmarkDecodeByteVector16(perftest::RepeatState* state) {
  return decode_benchmark_util::DecodeBenchmark(state, benchmark_suite::Build_ByteVector_16,
                                                DecodeByteVector);
}
bool BenchmarkDecodeByteVector256(perftest::RepeatState* state) {
  return decode_benchmark_util::DecodeBenchmark(state, benchmark_suite::Build_ByteVector_256,
                                                DecodeByteVector);
}
bool BenchmarkDecodeByteVector4096(perftest::RepeatState* state) {
  return decode_benchmark_util::DecodeBenchmark(state, benchmark_suite::Build_ByteVector_4096,
                                                DecodeByteVector);
}

void RegisterTests() {
  perftest::RegisterTest("Reference/Encode/ByteVector/16/WallTime/Steps",
                         BenchmarkEncodeByteVector16);
  perftest::RegisterTest("Reference/Encode/ByteVector/256/WallTime/Steps",
                         BenchmarkEncodeByteVector256);
  perftest::RegisterTest("Reference/Encode/ByteVector/4096/WallTime/Steps",
                         BenchmarkEncodeByteVector4096);
  perftest::RegisterTest("Reference/Decode/ByteVector/16/WallTime/Steps",
                         BenchmarkDecodeByteVector16);
  perftest::RegisterTest("Reference/Decode/ByteVector/256/WallTime/Steps",
                         BenchmarkDecodeByteVector256);
  perftest::RegisterTest("Reference/Decode/ByteVector/4096/WallTime/Steps",
                         BenchmarkDecodeByteVector4096);
}
PERFTEST_CTOR(RegisterTests)

}  // namespace
