1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/CAS/BuiltinObjectHasher.h"
10#include "llvm/Support/BLAKE3.h"
11
12using namespace llvm;
13using namespace llvm::cas;
14
15template <class HasherT>
16Expected<typename BuiltinObjectHasher<HasherT>::HashT>
17BuiltinObjectHasher<HasherT>::hashFile(StringRef FilePath) {
18 BuiltinObjectHasher H;
19 H.updateSize(0); // 0 refs
20
21 sys::fs::file_t FD;
22 if (Error E = sys::fs::openNativeFileForRead(Name: FilePath).moveInto(Value&: FD))
23 return E;
24
25 sys::fs::file_status Status;
26 std::error_code EC = sys::fs::status(FD, Result&: Status);
27 if (EC)
28 return createFileError(F: FilePath, EC);
29 // FIXME: Do we need to add a hash of the data size? If we remove that we can
30 // avoid needing to read the file size before reading the file contents.
31 H.updateSize(Status.getSize());
32
33 size_t ChunkSize = sys::fs::DefaultReadChunkSize;
34 SmallVector<char, 0> Buffer;
35 Buffer.resize_for_overwrite(N: ChunkSize);
36 for (;;) {
37 Expected<size_t> ReadBytes =
38 sys::fs::readNativeFile(FileHandle: FD, Buf: MutableArrayRef(Buffer.begin(), ChunkSize));
39 if (!ReadBytes)
40 return ReadBytes.takeError();
41 if (*ReadBytes == 0)
42 break;
43 H.Hasher.update(toStringRef(Input: ArrayRef(Buffer).take_front(N: *ReadBytes)));
44 }
45
46 return H.finish();
47}
48
49// Provide the definition for when using the BLAKE3 hasher.
50template Expected<BuiltinObjectHasher<BLAKE3>::HashT>
51BuiltinObjectHasher<BLAKE3>::hashFile(StringRef FilePath);
52