// Copyright (c) 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "spirv-tools/libspirv.hpp"

#include "table.h"

namespace spvtools {

// Structs for holding the data members for SpvTools.
struct SpirvTools::Impl {
  explicit Impl(spv_target_env env) : context(spvContextCreate(env)) {
    // The default consumer in spv_context_t is a null consumer, which provides
    // equivalent functionality (from the user's perspective) as a real consumer
    // does nothing.
  }
  ~Impl() { spvContextDestroy(context); }

  spv_context context;  // C interface context object.
};

SpirvTools::SpirvTools(spv_target_env env) : impl_(new Impl(env)) {}

SpirvTools::~SpirvTools() {}

void SpirvTools::SetMessageConsumer(MessageConsumer consumer) {
  libspirv::SetContextMessageConsumer(impl_->context, std::move(consumer));
}

bool SpirvTools::Assemble(const std::string& text,
                          std::vector<uint32_t>* binary,
                          uint32_t options) const {
  return Assemble(text.data(), text.size(), binary, options);
}

bool SpirvTools::Assemble(const char* text, const size_t text_size,
                          std::vector<uint32_t>* binary,
                          uint32_t options) const {
  spv_binary spvbinary = nullptr;
  spv_result_t status = spvTextToBinaryWithOptions(
      impl_->context, text, text_size, options, &spvbinary, nullptr);
  if (status == SPV_SUCCESS) {
    binary->assign(spvbinary->code, spvbinary->code + spvbinary->wordCount);
  }
  spvBinaryDestroy(spvbinary);
  return status == SPV_SUCCESS;
}

bool SpirvTools::Disassemble(const std::vector<uint32_t>& binary,
                             std::string* text, uint32_t options) const {
  return Disassemble(binary.data(), binary.size(), text, options);
}

bool SpirvTools::Disassemble(const uint32_t* binary, const size_t binary_size,
                             std::string* text, uint32_t options) const {
  spv_text spvtext = nullptr;
  spv_result_t status = spvBinaryToText(impl_->context, binary, binary_size,
                                        options, &spvtext, nullptr);
  if (status == SPV_SUCCESS) {
    text->assign(spvtext->str, spvtext->str + spvtext->length);
  }
  spvTextDestroy(spvtext);
  return status == SPV_SUCCESS;
}

bool SpirvTools::Validate(const std::vector<uint32_t>& binary) const {
  return Validate(binary.data(), binary.size());
}

bool SpirvTools::Validate(const uint32_t* binary,
                          const size_t binary_size) const {
  return spvValidateBinary(impl_->context, binary, binary_size, nullptr) ==
         SPV_SUCCESS;
}

bool SpirvTools::Validate(const uint32_t* binary, const size_t binary_size,
                          const spvtools::ValidatorOptions& options) const {
  spv_const_binary_t the_binary{binary, binary_size};
  return spvValidateWithOptions(impl_->context, options, &the_binary,
                                nullptr) == SPV_SUCCESS;
}

}  // namespace spvtools
