//===- BuiltinCAS.cpp -------------------------------------------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// #include "BuiltinCAS.h" #include "llvm/ADT/StringExtras.h" #include "llvm/CAS/BuiltinObjectHasher.h" #include "llvm/Support/Process.h" using namespace llvm; using namespace llvm::cas; using namespace llvm::cas::builtin; static StringRef getCASIDPrefix() { return "llvmcas://"; } void BuiltinCASContext::anchor() {} Expected BuiltinCASContext::parseID(StringRef Reference) { if (!Reference.consume_front(getCASIDPrefix())) return createStringError(std::make_error_code(std::errc::invalid_argument), "invalid cas-id '" + Reference + "'"); // FIXME: Allow shortened references? if (Reference.size() != 2 * sizeof(HashType)) return createStringError(std::make_error_code(std::errc::invalid_argument), "wrong size for cas-id hash '" + Reference + "'"); std::string Binary; if (!tryGetFromHex(Reference, Binary)) return createStringError(std::make_error_code(std::errc::invalid_argument), "invalid hash in cas-id '" + Reference + "'"); assert(Binary.size() == sizeof(HashType)); HashType Digest; llvm::copy(Binary, Digest.data()); return Digest; } Expected BuiltinCAS::parseID(StringRef Reference) { Expected Digest = BuiltinCASContext::parseID(Reference); if (!Digest) return Digest.takeError(); return CASID::create(&getContext(), toStringRef(*Digest)); } void BuiltinCASContext::printID(ArrayRef Digest, raw_ostream &OS) { SmallString<64> Hash; toHex(Digest, /*LowerCase=*/true, Hash); OS << getCASIDPrefix() << Hash; } void BuiltinCASContext::printIDImpl(raw_ostream &OS, const CASID &ID) const { BuiltinCASContext::printID(ID.getHash(), OS); } const BuiltinCASContext &BuiltinCASContext::getDefaultContext() { static BuiltinCASContext DefaultContext; return DefaultContext; } Expected BuiltinCAS::store(ArrayRef Refs, ArrayRef Data) { return storeImpl(BuiltinObjectHasher::hashObject(*this, Refs, Data), Refs, Data); } Error BuiltinCAS::validate(const CASID &ID) { auto Ref = getReference(ID); if (!Ref) return createUnknownObjectError(ID); auto Handle = load(*Ref); if (!Handle) return Handle.takeError(); auto Proxy = ObjectProxy::load(*this, *Ref, *Handle); SmallVector Refs; if (auto E = Proxy.forEachReference([&](ObjectRef Ref) -> Error { Refs.push_back(Ref); return Error::success(); })) return E; ArrayRef Data(Proxy.getData().data(), Proxy.getData().size()); auto Hash = BuiltinObjectHasher::hashObject(*this, Refs, Data); if (!ID.getHash().equals(Hash)) return createCorruptObjectError(ID); return Error::success(); }