//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implements \c ObjectStore and \c ActionCache on top of a dynamically loaded
/// plugin that provides the C API in \c "llvm-c/CAS/PluginAPI_functions.h".
///
/// The asynchronous entry points of the plugin API are not called yet; they
/// will be wired up once \c ObjectStore and \c ActionCache grow asynchronous
/// interfaces.
///
//===----------------------------------------------------------------------===//

#include "PluginAPI.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/CAS/ActionCache.h"
#include "llvm/CAS/ObjectStore.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace llvm;
using namespace llvm::cas;

namespace {

class PluginCASContext : public CASContext {
public:
  void printIDImpl(raw_ostream &OS, const CASID &ID) const final;

  StringRef getHashSchemaIdentifier() const final { return SchemaName; }

  static Expected<std::shared_ptr<PluginCASContext>>
  create(StringRef PluginPath, StringRef OnDiskPath,
         ArrayRef<std::pair<std::string, std::string>> PluginArgs);

  ~PluginCASContext() { Functions.cas_dispose(c_cas); }

  llcas_functions_t Functions{};
  llcas_cas_t c_cas = nullptr;
  std::string SchemaName;

  static Error errorAndDispose(char *c_err, const llcas_functions_t &Funcs) {
    Error E = createStringError(inconvertibleErrorCode(), c_err);
    Funcs.string_dispose(c_err);
    return E;
  }

  Error errorAndDispose(char *c_err) const {
    return errorAndDispose(c_err, Functions);
  }
};

} // anonymous namespace

void PluginCASContext::printIDImpl(raw_ostream &OS, const CASID &ID) const {
  ArrayRef<uint8_t> Hash = ID.getHash();
  char *c_printed_id = nullptr;
  char *c_err = nullptr;
  if (Functions.digest_print(c_cas, llcas_digest_t{Hash.data(), Hash.size()},
                             &c_printed_id, &c_err))
    report_fatal_error(errorAndDispose(c_err));
  OS << c_printed_id;
  Functions.string_dispose(c_printed_id);
}

/// Loads the plugin library at \p PluginPath and looks up its functions.
static Expected<llcas_functions_t> loadPluginFunctions(StringRef PluginPath) {
  auto reportError = [PluginPath](const Twine &Description) -> Error {
    std::error_code EC = inconvertibleErrorCode();
    return createStringError(EC, "error loading '" + PluginPath +
                                     "': " + Description);
  };

  SmallString<256> PathBuf = PluginPath;
  std::string ErrMsg;
  sys::DynamicLibrary Lib =
      sys::DynamicLibrary::getPermanentLibrary(PathBuf.c_str(), &ErrMsg);
  if (!Lib.isValid())
    return reportError(ErrMsg);

  llcas_functions_t Functions{};

#define CASPLUGINAPI_FUNCTION(name, required)                                  \
  if (!(Functions.name = (decltype(llcas_functions_t::name))                   \
                             Lib.getAddressOfSymbol("llcas_" #name))) {        \
    if (required)                                                              \
      return reportError("failed symbol 'llcas_" #name "' lookup");            \
  }
#include "PluginAPI_functions.def"
#undef CASPLUGINAPI_FUNCTION

  return Functions;
}

/// Creates a \c llcas_cas_options_t for \p OnDiskPath and \p PluginArgs. On
/// success the caller is responsible for disposing it.
static Expected<llcas_cas_options_t>
createPluginOptions(const llcas_functions_t &Functions, StringRef OnDiskPath,
                    ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
  llcas_cas_options_t c_opts = Functions.cas_options_create();
  Functions.cas_options_set_client_version(c_opts, LLCAS_VERSION_MAJOR,
                                           LLCAS_VERSION_MINOR);
  SmallString<256> OnDiskPathBuf = OnDiskPath;
  Functions.cas_options_set_ondisk_path(c_opts, OnDiskPathBuf.c_str());
  for (const auto &Pair : PluginArgs) {
    char *c_err = nullptr;
    if (Functions.cas_options_set_option(c_opts, Pair.first.c_str(),
                                         Pair.second.c_str(), &c_err)) {
      Functions.cas_options_dispose(c_opts);
      return PluginCASContext::errorAndDispose(c_err, Functions);
    }
  }
  return c_opts;
}

Expected<std::shared_ptr<PluginCASContext>> PluginCASContext::create(
    StringRef PluginPath, StringRef OnDiskPath,
    ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
  llcas_functions_t Functions{};
  if (Error E = loadPluginFunctions(PluginPath).moveInto(Functions))
    return std::move(E);

  llcas_cas_options_t c_opts = nullptr;
  if (Error E = createPluginOptions(Functions, OnDiskPath, PluginArgs)
                    .moveInto(c_opts))
    return std::move(E);
  scope_exit DisposeOptions([&]() { Functions.cas_options_dispose(c_opts); });

  char *c_err = nullptr;
  llcas_cas_t c_cas = Functions.cas_create(c_opts, &c_err);
  if (!c_cas)
    return errorAndDispose(c_err, Functions);

  char *c_schema = Functions.cas_get_hash_schema_name(c_cas);
  std::string SchemaName = c_schema;
  Functions.string_dispose(c_schema);

  auto Ctx = std::make_shared<PluginCASContext>();
  Ctx->Functions = Functions;
  Ctx->c_cas = c_cas;
  Ctx->SchemaName = std::move(SchemaName);
  return Ctx;
}

//===----------------------------------------------------------------------===//
// ObjectStore API
//===----------------------------------------------------------------------===//

namespace {

class PluginObjectStore : public ObjectStore {
public:
  Expected<CASID> parseID(StringRef ID) final;
  Expected<ObjectRef> store(ArrayRef<ObjectRef> Refs,
                            ArrayRef<char> Data) final;
  Expected<ObjectRef> storeFromFile(StringRef Path) final;
  Error exportDataToFile(ObjectHandle Node, StringRef Path) const final;
  CASID getID(ObjectRef Ref) const final;
  std::optional<ObjectRef> getReference(const CASID &ID) const final;
  Expected<bool> isMaterialized(ObjectRef Ref) const final;
  Expected<std::optional<ObjectHandle>> loadIfExists(ObjectRef Ref) final;
  uint64_t getDataSize(ObjectHandle Node) const final;
  Error forEachRef(ObjectHandle Node,
                   function_ref<Error(ObjectRef)> Callback) const final;
  ObjectRef readRef(ObjectHandle Node, size_t I) const final;
  size_t getNumRefs(ObjectHandle Node) const final;
  ArrayRef<char> getData(ObjectHandle Node,
                         bool RequiresNullTerminator = false) const final;
  std::unique_ptr<MemoryBuffer>
  getStandaloneMemoryBufferImpl(ObjectHandle Node, StringRef Name,
                                bool RequiresNullTerminator) final;
  Error validateObject(const CASID &ID) final {
    // Not supported yet. Always return success.
    return Error::success();
  }

  Error validate(bool CheckHash) const final;

  Error setSizeLimit(std::optional<uint64_t> SizeLimit) final;
  Expected<std::optional<uint64_t>> getStorageSize() const final;
  Error pruneStorageData() final;

  PluginObjectStore(std::shared_ptr<PluginCASContext>);

  /// Exposes \c makeObjectRef to the file-local helpers below.
  ObjectRef makeRef(uint64_t InternalRef) const {
    return makeObjectRef(InternalRef);
  }

  std::shared_ptr<PluginCASContext> Ctx;
};

} // anonymous namespace

Expected<CASID> PluginObjectStore::parseID(StringRef ID) {
  // Use big enough stack so that we don't have to allocate in the heap.
  SmallString<148> IDBuf(ID);
  SmallVector<uint8_t, 68> BytesBuf(68);

  auto parseDigest = [&]() -> Expected<unsigned> {
    char *c_err = nullptr;
    unsigned NumBytes = Ctx->Functions.digest_parse(
        Ctx->c_cas, IDBuf.c_str(), BytesBuf.data(), BytesBuf.size(), &c_err);
    if (NumBytes == 0)
      return Ctx->errorAndDispose(c_err);
    return NumBytes;
  };

  Expected<unsigned> NumBytes = parseDigest();
  if (!NumBytes)
    return NumBytes.takeError();

  if (*NumBytes > BytesBuf.size()) {
    BytesBuf.resize(*NumBytes);
    NumBytes = parseDigest();
    if (!NumBytes)
      return NumBytes.takeError();
    assert(*NumBytes == BytesBuf.size());
  } else {
    BytesBuf.truncate(*NumBytes);
  }

  return CASID::create(Ctx.get(), toStringRef(BytesBuf));
}

Expected<ObjectRef> PluginObjectStore::store(ArrayRef<ObjectRef> Refs,
                                             ArrayRef<char> Data) {
  SmallVector<llcas_objectid_t, 64> c_ids;
  c_ids.reserve(Refs.size());
  for (ObjectRef Ref : Refs) {
    c_ids.push_back(llcas_objectid_t{Ref.getInternalRef(*this)});
  }

  llcas_objectid_t c_stored_id;
  char *c_err = nullptr;
  if (Ctx->Functions.cas_store_object(
          Ctx->c_cas, llcas_data_t{Data.data(), Data.size()}, c_ids.data(),
          c_ids.size(), &c_stored_id, &c_err))
    return Ctx->errorAndDispose(c_err);

  return makeObjectRef(c_stored_id.opaque);
}

Expected<ObjectRef> PluginObjectStore::storeFromFile(StringRef Path) {
  if (!Ctx->Functions.cas_store_from_filepath)
    return ObjectStore::storeFromFile(Path);

  llcas_objectid_t c_stored_id;
  char *c_err = nullptr;
  std::string PathStr = Path.str();
  if (Ctx->Functions.cas_store_from_filepath(Ctx->c_cas, PathStr.c_str(),
                                             &c_stored_id, &c_err))
    return Ctx->errorAndDispose(c_err);

  return makeObjectRef(c_stored_id.opaque);
}

Error PluginObjectStore::exportDataToFile(ObjectHandle Node,
                                          StringRef Path) const {
  if (!Ctx->Functions.loaded_object_export_data_to_filepath)
    return ObjectStore::exportDataToFile(Node, Path);

  char *c_err = nullptr;
  std::string PathStr = Path.str();
  if (Ctx->Functions.loaded_object_export_data_to_filepath(
          Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)},
          PathStr.c_str(), &c_err))
    return Ctx->errorAndDispose(c_err);

  return Error::success();
}

static StringRef toStringRef(llcas_digest_t c_digest) {
  return StringRef((const char *)c_digest.data, c_digest.size);
}

CASID PluginObjectStore::getID(ObjectRef Ref) const {
  llcas_objectid_t c_id{Ref.getInternalRef(*this)};
  llcas_digest_t c_digest =
      Ctx->Functions.objectid_get_digest(Ctx->c_cas, c_id);
  return CASID::create(Ctx.get(), toStringRef(c_digest));
}

std::optional<ObjectRef>
PluginObjectStore::getReference(const CASID &ID) const {
  ArrayRef<uint8_t> Hash = ID.getHash();
  llcas_objectid_t c_id;
  char *c_err = nullptr;
  if (Ctx->Functions.cas_get_objectid(
          Ctx->c_cas, llcas_digest_t{Hash.data(), Hash.size()}, &c_id, &c_err))
    report_fatal_error(Ctx->errorAndDispose(c_err));

  return makeObjectRef(c_id.opaque);
}

Expected<bool> PluginObjectStore::isMaterialized(ObjectRef Ref) const {
  llcas_objectid_t c_id{Ref.getInternalRef(*this)};
  char *c_err = nullptr;
  llcas_lookup_result_t c_result = Ctx->Functions.cas_contains_object(
      Ctx->c_cas, c_id, /*globally=*/false, &c_err);
  switch (c_result) {
  case LLCAS_LOOKUP_RESULT_SUCCESS:
    return true;
  case LLCAS_LOOKUP_RESULT_NOTFOUND:
    return false;
  case LLCAS_LOOKUP_RESULT_ERROR:
    return Ctx->errorAndDispose(c_err);
  }
  llvm_unreachable("unknown llcas_lookup_result_t value");
}

Expected<std::optional<ObjectHandle>>
PluginObjectStore::loadIfExists(ObjectRef Ref) {
  llcas_objectid_t c_id{Ref.getInternalRef(*this)};
  llcas_loaded_object_t c_obj;
  char *c_err = nullptr;
  llcas_lookup_result_t c_result =
      Ctx->Functions.cas_load_object(Ctx->c_cas, c_id, &c_obj, &c_err);
  switch (c_result) {
  case LLCAS_LOOKUP_RESULT_SUCCESS:
    return makeObjectHandle(c_obj.opaque);
  case LLCAS_LOOKUP_RESULT_NOTFOUND:
    return std::nullopt;
  case LLCAS_LOOKUP_RESULT_ERROR:
    return Ctx->errorAndDispose(c_err);
  }
  llvm_unreachable("unknown llcas_lookup_result_t value");
}

namespace {

class ObjectRefsWrapper {
public:
  ObjectRefsWrapper(const ObjectHandle &Node, const PluginObjectStore &Store)
      : Store(Store), Ctx(*Store.Ctx) {
    llcas_loaded_object_t c_obj{Node.getInternalRef(Store)};
    this->c_refs = Ctx.Functions.loaded_object_get_refs(Ctx.c_cas, c_obj);
  }

  size_t size() const {
    return Ctx.Functions.object_refs_get_count(Ctx.c_cas, c_refs);
  }

  ObjectRef operator[](size_t I) const {
    llcas_objectid_t c_id =
        Ctx.Functions.object_refs_get_id(Ctx.c_cas, c_refs, I);
    return Store.makeRef(c_id.opaque);
  }

private:
  const PluginObjectStore &Store;
  PluginCASContext &Ctx;
  llcas_object_refs_t c_refs;
};

} // namespace

// FIXME: Replace forEachRef/readRef/getNumRefs APIs with an iterator interface.
Error PluginObjectStore::forEachRef(
    ObjectHandle Node, function_ref<Error(ObjectRef)> Callback) const {
  ObjectRefsWrapper Refs(Node, *this);
  for (unsigned I = 0, E = Refs.size(); I != E; ++I) {
    if (Error E = Callback(Refs[I]))
      return E;
  }
  return Error::success();
}

ObjectRef PluginObjectStore::readRef(ObjectHandle Node, size_t I) const {
  ObjectRefsWrapper Refs(Node, *this);
  return Refs[I];
}

size_t PluginObjectStore::getNumRefs(ObjectHandle Node) const {
  ObjectRefsWrapper Refs(Node, *this);
  return Refs.size();
}

// FIXME: Remove getDataSize(ObjectHandle) from API requirement,
// \c getData(ObjectHandle) should be enough.
uint64_t PluginObjectStore::getDataSize(ObjectHandle Node) const {
  ArrayRef<char> Data = getData(Node);
  return Data.size();
}

ArrayRef<char> PluginObjectStore::getData(ObjectHandle Node,
                                          bool RequiresNullTerminator) const {
  // FIXME: Remove RequiresNullTerminator from ObjectStore API requirement?
  // It is a requirement for the plugin API.
  llcas_data_t c_data = Ctx->Functions.loaded_object_get_data(
      Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)});
  return ArrayRef((const char *)c_data.data, c_data.size);
}

namespace {
/// A MemoryBuffer over a plugin's standalone buffer, which it releases when
/// destroyed. It holds the dispose function directly rather than the
/// \c llcas_cas_t, since the point of the buffer is to outlive that.
class PluginStandaloneMemoryBuffer final : public MemoryBuffer {
public:
  using DisposeFn = void (*)(llcas_data_t);

  PluginStandaloneMemoryBuffer(llcas_data_t Data, StringRef Name,
                               DisposeFn Dispose)
      : Data(Data), Name(Name.str()), Dispose(Dispose) {
    const char *Start = static_cast<const char *>(Data.data);
    init(Start, Start + Data.size, /*RequiresNullTerminator=*/true);
  }

  ~PluginStandaloneMemoryBuffer() override { Dispose(Data); }

  StringRef getBufferIdentifier() const final { return Name; }

  BufferKind getBufferKind() const final { return MemoryBuffer_Malloc; }

private:
  llcas_data_t Data;
  std::string Name;
  DisposeFn Dispose;
};
} // namespace

std::unique_ptr<MemoryBuffer> PluginObjectStore::getStandaloneMemoryBufferImpl(
    ObjectHandle Node, StringRef Name, bool RequiresNullTerminator) {
  // Both halves are needed: without the disposer there is no way to release
  // what the getter hands out.
  if (!Ctx->Functions.loaded_object_get_standalone_data ||
      !Ctx->Functions.standalone_data_dispose)
    return ObjectStore::getStandaloneMemoryBufferImpl(Node, Name,
                                                      RequiresNullTerminator);

  llcas_data_t c_data = Ctx->Functions.loaded_object_get_standalone_data(
      Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)});
  if (!c_data.data)
    return ObjectStore::getStandaloneMemoryBufferImpl(Node, Name,
                                                      RequiresNullTerminator);

  return std::make_unique<PluginStandaloneMemoryBuffer>(
      c_data, Name, Ctx->Functions.standalone_data_dispose);
}

Error PluginObjectStore::setSizeLimit(std::optional<uint64_t> SizeLimit) {
  if (Ctx->Functions.cas_set_ondisk_size_limit) {
    char *c_err = nullptr;
    if (Ctx->Functions.cas_set_ondisk_size_limit(Ctx->c_cas,
                                                 SizeLimit.value_or(0), &c_err))
      return Ctx->errorAndDispose(c_err);
  }
  return Error::success();
}

Expected<std::optional<uint64_t>> PluginObjectStore::getStorageSize() const {
  if (!Ctx->Functions.cas_get_ondisk_size)
    return std::nullopt;
  char *c_err = nullptr;
  int64_t ret = Ctx->Functions.cas_get_ondisk_size(Ctx->c_cas, &c_err);
  switch (ret) {
  case -1:
    return std::nullopt;
  case -2:
    return Ctx->errorAndDispose(c_err);
  default:
    return ret;
  }
}

Error PluginObjectStore::pruneStorageData() {
  if (Ctx->Functions.cas_prune_ondisk_data) {
    char *c_err = nullptr;
    if (Ctx->Functions.cas_prune_ondisk_data(Ctx->c_cas, &c_err))
      return Ctx->errorAndDispose(c_err);
  }
  return Error::success();
}

Error PluginObjectStore::validate(bool CheckHash) const {
  if (Ctx->Functions.cas_validate) {
    char *c_err = nullptr;
    if (Ctx->Functions.cas_validate(Ctx->c_cas, CheckHash, &c_err))
      return Ctx->errorAndDispose(c_err);
    return Error::success();
  }
  return createStringError("plugin cas doesn't support validation");
}

PluginObjectStore::PluginObjectStore(std::shared_ptr<PluginCASContext> CASCtx)
    : ObjectStore(*CASCtx), Ctx(std::move(CASCtx)) {}

//===----------------------------------------------------------------------===//
// ActionCache API
//===----------------------------------------------------------------------===//

namespace {

class PluginActionCache : public ActionCache {
public:
  Expected<std::optional<CASID>> getImpl(ArrayRef<uint8_t> ResolvedKey,
                                         bool CanBeDistributed) const final;

  Error putImpl(ArrayRef<uint8_t> ResolvedKey, const CASID &Result,
                bool CanBeDistributed) final;

  PluginActionCache(std::shared_ptr<PluginCASContext>);

  Error validate() const final;

private:
  std::shared_ptr<PluginCASContext> Ctx;
};

} // anonymous namespace

Expected<std::optional<CASID>>
PluginActionCache::getImpl(ArrayRef<uint8_t> ResolvedKey,
                           bool CanBeDistributed) const {
  llcas_objectid_t c_value;
  char *c_err = nullptr;
  llcas_lookup_result_t c_result = Ctx->Functions.actioncache_get_for_digest(
      Ctx->c_cas, llcas_digest_t{ResolvedKey.data(), ResolvedKey.size()},
      &c_value, CanBeDistributed, &c_err);
  switch (c_result) {
  case LLCAS_LOOKUP_RESULT_SUCCESS: {
    llcas_digest_t c_digest =
        Ctx->Functions.objectid_get_digest(Ctx->c_cas, c_value);
    return CASID::create(Ctx.get(), toStringRef(c_digest));
  }
  case LLCAS_LOOKUP_RESULT_NOTFOUND:
    return std::nullopt;
  case LLCAS_LOOKUP_RESULT_ERROR:
    return Ctx->errorAndDispose(c_err);
  }
  llvm_unreachable("unknown llcas_lookup_result_t value");
}

Error PluginActionCache::putImpl(ArrayRef<uint8_t> ResolvedKey,
                                 const CASID &Result, bool CanBeDistributed) {
  ArrayRef<uint8_t> Hash = Result.getHash();
  llcas_objectid_t c_value;
  char *c_err = nullptr;
  if (Ctx->Functions.cas_get_objectid(Ctx->c_cas,
                                      llcas_digest_t{Hash.data(), Hash.size()},
                                      &c_value, &c_err))
    return Ctx->errorAndDispose(c_err);

  if (Ctx->Functions.actioncache_put_for_digest(
          Ctx->c_cas, llcas_digest_t{ResolvedKey.data(), ResolvedKey.size()},
          c_value, CanBeDistributed, &c_err))
    return Ctx->errorAndDispose(c_err);

  return Error::success();
}

PluginActionCache::PluginActionCache(std::shared_ptr<PluginCASContext> CASCtx)
    : ActionCache(*CASCtx), Ctx(std::move(CASCtx)) {}

Error PluginActionCache::validate() const {
  if (Ctx->Functions.actioncache_validate) {
    char *c_err = nullptr;
    if (Ctx->Functions.actioncache_validate(Ctx->c_cas, &c_err))
      return Ctx->errorAndDispose(c_err);
    return Error::success();
  }
  return createStringError("plugin action cache doesn't support validation");
}

//===----------------------------------------------------------------------===//
// createPluginCASDatabases API
//===----------------------------------------------------------------------===//

Expected<std::pair<std::shared_ptr<ObjectStore>, std::shared_ptr<ActionCache>>>
cas::createPluginCASDatabases(
    StringRef PluginPath, StringRef OnDiskPath,
    ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
  std::shared_ptr<PluginCASContext> Ctx;
  if (Error E = PluginCASContext::create(PluginPath, OnDiskPath, PluginArgs)
                    .moveInto(Ctx))
    return std::move(E);
  auto CAS = std::make_shared<PluginObjectStore>(Ctx);
  auto AC = std::make_shared<PluginActionCache>(std::move(Ctx));
  return std::make_pair(std::move(CAS), std::move(AC));
}

/// Loads the plugin and calls \p Fn with a \c llcas_cas_options_t for
/// \p OnDiskPath and \p PluginArgs, converting the returned
/// \c llcas_validation_result_t.
static Expected<ValidationResult> callPluginValidationFunction(
    StringRef PluginPath, StringRef OnDiskPath,
    ArrayRef<std::pair<std::string, std::string>> PluginArgs,
    function_ref<Expected<llcas_validation_result_t>(
        const llcas_functions_t &, llcas_cas_options_t, char **)>
        Fn) {
  llcas_functions_t Functions{};
  if (Error E = loadPluginFunctions(PluginPath).moveInto(Functions))
    return std::move(E);

  llcas_cas_options_t c_opts = nullptr;
  if (Error E = createPluginOptions(Functions, OnDiskPath, PluginArgs)
                    .moveInto(c_opts))
    return std::move(E);
  scope_exit DisposeOptions([&]() { Functions.cas_options_dispose(c_opts); });

  char *c_err = nullptr;
  llcas_validation_result_t Result;
  if (Error E = Fn(Functions, c_opts, &c_err).moveInto(Result))
    return std::move(E);
  switch (Result) {
  case LLCAS_VALIDATION_RESULT_VALID:
    return ValidationResult::Valid;
  case LLCAS_VALIDATION_RESULT_RECOVERED:
    return ValidationResult::Recovered;
  case LLCAS_VALIDATION_RESULT_SKIPPED:
    return ValidationResult::Skipped;
  case LLCAS_VALIDATION_RESULT_ERROR:
    return PluginCASContext::errorAndDispose(c_err, Functions);
  }
  // The plugin is outside of our control, so an unknown result is an error
  // rather than unreachable. Include the plugin's error message, if any.
  std::string Msg;
  raw_string_ostream OS(Msg);
  OS << "unknown validation result " << static_cast<int>(Result) << " from '"
     << PluginPath << "'";
  if (c_err) {
    OS << ": " << c_err;
    Functions.string_dispose(c_err);
  }
  return createStringError(Msg);
}

Expected<ValidationResult> cas::validatePluginCASDatabasesIfNeeded(
    StringRef PluginPath, StringRef OnDiskPath,
    ArrayRef<std::pair<std::string, std::string>> PluginArgs, bool CheckHash,
    bool ForceValidation) {
  return callPluginValidationFunction(
      PluginPath, OnDiskPath, PluginArgs,
      [&](const llcas_functions_t &Functions, llcas_cas_options_t c_opts,
          char **c_err) -> Expected<llcas_validation_result_t> {
        if (!Functions.cas_validate_if_needed)
          return createStringError(
              "plugin cas doesn't support validate-if-needed");
        return Functions.cas_validate_if_needed(c_opts, CheckHash,
                                                ForceValidation, c_err);
      });
}

Expected<ValidationResult> cas::recoverPluginCASDatabases(
    StringRef PluginPath, StringRef OnDiskPath,
    ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
  return callPluginValidationFunction(
      PluginPath, OnDiskPath, PluginArgs,
      [&](const llcas_functions_t &Functions, llcas_cas_options_t c_opts,
          char **c_err) -> Expected<llcas_validation_result_t> {
        if (!Functions.cas_recover_ondisk_data)
          return createStringError("plugin cas doesn't support recovery");
        return Functions.cas_recover_ondisk_data(c_opts, c_err);
      });
}
