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

#include "src/execution/isolate.h"
#include "src/wasm/streaming-decoder.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-serialization.h"

namespace v8 {
namespace internal {
namespace wasm {

class V8_EXPORT_PRIVATE SyncStreamingDecoder : public StreamingDecoder {
 public:
  SyncStreamingDecoder(Isolate* isolate, const WasmFeatures& enabled,
                       Handle<Context> context,
                       const char* api_method_name_for_errors,
                       std::shared_ptr<CompilationResultResolver> resolver)
      : isolate_(isolate),
        enabled_(enabled),
        context_(context),
        api_method_name_for_errors_(api_method_name_for_errors),
        resolver_(resolver) {}

  // The buffer passed into OnBytesReceived is owned by the caller.
  void OnBytesReceived(Vector<const uint8_t> bytes) override {
    buffer_.emplace_back(bytes.size());
    CHECK_EQ(buffer_.back().size(), bytes.size());
    std::memcpy(buffer_.back().data(), bytes.data(), bytes.size());
    buffer_size_ += bytes.size();
  }

  void Finish() override {
    // We copy all received chunks into one byte buffer.
    auto bytes = std::make_unique<uint8_t[]>(buffer_size_);
    uint8_t* destination = bytes.get();
    for (auto& chunk : buffer_) {
      std::memcpy(destination, chunk.data(), chunk.size());
      destination += chunk.size();
    }
    CHECK_EQ(destination - bytes.get(), buffer_size_);

    // Check if we can deserialize the module from cache.
    if (deserializing()) {
      HandleScope scope(isolate_);
      SaveAndSwitchContext saved_context(isolate_, *context_);

      MaybeHandle<WasmModuleObject> module_object = DeserializeNativeModule(
          isolate_, compiled_module_bytes_,
          Vector<const uint8_t>(bytes.get(), buffer_size_), url());

      if (!module_object.is_null()) {
        Handle<WasmModuleObject> module = module_object.ToHandleChecked();
        resolver_->OnCompilationSucceeded(module);
        return;
      }
    }

    // Compile the received bytes synchronously.
    ModuleWireBytes wire_bytes(bytes.get(), bytes.get() + buffer_size_);
    ErrorThrower thrower(isolate_, api_method_name_for_errors_);
    MaybeHandle<WasmModuleObject> module_object =
        isolate_->wasm_engine()->SyncCompile(isolate_, enabled_, &thrower,
                                             wire_bytes);
    if (thrower.error()) {
      resolver_->OnCompilationFailed(thrower.Reify());
      return;
    }
    Handle<WasmModuleObject> module = module_object.ToHandleChecked();
    if (module_compiled_callback_) {
      module_compiled_callback_(module->shared_native_module());
    }
    resolver_->OnCompilationSucceeded(module);
  }

  void Abort() override {
    // Abort is fully handled by the API, we only clear the buffer.
    buffer_.clear();
  }

  void NotifyCompilationEnded() override { buffer_.clear(); }

  void NotifyNativeModuleCreated(
      const std::shared_ptr<NativeModule>&) override {
    // This function is only called from the {AsyncCompileJob}.
    UNREACHABLE();
  }

 private:
  Isolate* isolate_;
  const WasmFeatures enabled_;
  Handle<Context> context_;
  const char* api_method_name_for_errors_;
  std::shared_ptr<CompilationResultResolver> resolver_;

  std::vector<std::vector<uint8_t>> buffer_;
  size_t buffer_size_ = 0;
};

std::unique_ptr<StreamingDecoder> StreamingDecoder::CreateSyncStreamingDecoder(
    Isolate* isolate, const WasmFeatures& enabled, Handle<Context> context,
    const char* api_method_name_for_errors,
    std::shared_ptr<CompilationResultResolver> resolver) {
  return std::make_unique<SyncStreamingDecoder>(isolate, enabled, context,
                                                api_method_name_for_errors,
                                                std::move(resolver));
}
}  // namespace wasm
}  // namespace internal
}  // namespace v8
