// Copyright 2023 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <lib/boot-options/boot-options.h>
#include <lib/fit/defer.h>

#include <vm/lz4_compressor.h>
#include <vm/physmap.h>

VmLz4Compressor::CompressResult VmLz4Compressor::Compress(const void *src, void *dst,
                                                          size_t dst_limit) {
  int compressed_result;
  int threshold = static_cast<int>(dst_limit);
  {
    Guard<Mutex> guard{&compress_lock_};
    compressed_result = LZ4_compress_fast_extState_fastReset(
        &stream_, static_cast<const char *>(src), static_cast<char *>(dst), PAGE_SIZE, threshold,
        acceleration_);
  }
  if (compressed_result == 0) {
    return FailTag{};
  }
  DEBUG_ASSERT(compressed_result > 0 && compressed_result <= threshold);
  size_t compressed_size = static_cast<size_t>(compressed_result);
  if (compressed_size == compressed_zero_.size()) {
    if (memcmp(dst, compressed_zero_.get(), compressed_size) == 0) {
      return ZeroTag{};
    }
  }
  return compressed_size;
}

void VmLz4Compressor::Decompress(const void *src, size_t src_len, void *dst) {
  int result = LZ4_decompress_safe(static_cast<const char *>(src), static_cast<char *>(dst),
                                   static_cast<int>(src_len), PAGE_SIZE);
  ASSERT(result == PAGE_SIZE);
}

void VmLz4Compressor::Dump() const {}

bool VmLz4Compressor::Init() {
  Guard<Mutex> guard{&compress_lock_};
  // Initialize the stream. As our stream should be exactly sized and aligned there is no reason for
  // this to return anything other than the original pointer.
  LZ4_stream_t *stream = LZ4_initStream(&stream_, sizeof(stream_));
  if (stream != &stream_) {
    return false;
  }

  // Zero page should compress quite well, so just use a small stack allocation.
  constexpr size_t kMaxZeroPageStorage = 128;
  char temp_zero_compress[kMaxZeroPageStorage];
  int compress_result = LZ4_compress_fast_extState_fastReset(
      &stream_, static_cast<const char *>(paddr_to_physmap(vm_get_zero_page_paddr())),
      temp_zero_compress, PAGE_SIZE, kMaxZeroPageStorage, acceleration_);
  if (compress_result == 0) {
    printf("ERROR: LZ4 failed to compress zero page with acceleration %d into %zu bytes\n",
           acceleration_, kMaxZeroPageStorage);
    return false;
  }
  DEBUG_ASSERT(compress_result > 0);
  size_t compressed_size = static_cast<size_t>(compress_result);
  DEBUG_ASSERT(compressed_size <= kMaxZeroPageStorage);
  // Now allocate the exact storage.
  fbl::AllocChecker ac;
  compressed_zero_ = fbl::MakeArray<char>(&ac, compressed_size);
  if (!ac.check()) {
    return false;
  }
  memcpy(compressed_zero_.get(), temp_zero_compress, compressed_size);

  return true;
}

fbl::RefPtr<VmLz4Compressor> VmLz4Compressor::Create() {
  const int acceleration = static_cast<int>(gBootOptions->compression_lz4_acceleration);

  fbl::AllocChecker ac;
  fbl::RefPtr<VmLz4Compressor> lz4 =
      fbl::AdoptRef<VmLz4Compressor>(new (&ac) VmLz4Compressor(acceleration));
  if (!ac.check()) {
    return nullptr;
  }

  if (!lz4->Init()) {
    return nullptr;
  }

  return lz4;
}
