summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/build_engine/expression/expression.cpp7
-rw-r--r--src/buildtool/build_engine/target_map/utils.cpp14
-rw-r--r--src/buildtool/crypto/TARGETS30
-rw-r--r--src/buildtool/crypto/hash_function.hpp20
-rw-r--r--src/buildtool/crypto/hash_generator.hpp127
-rw-r--r--src/buildtool/crypto/hash_impl.hpp40
-rw-r--r--src/buildtool/crypto/hash_impl_git.cpp42
-rw-r--r--src/buildtool/crypto/hash_impl_git.hpp10
-rw-r--r--src/buildtool/crypto/hash_impl_md5.cpp50
-rw-r--r--src/buildtool/crypto/hash_impl_md5.hpp10
-rw-r--r--src/buildtool/crypto/hash_impl_sha1.cpp11
-rw-r--r--src/buildtool/crypto/hash_impl_sha1.hpp5
-rw-r--r--src/buildtool/crypto/hash_impl_sha256.cpp11
-rw-r--r--src/buildtool/crypto/hash_impl_sha256.hpp5
-rw-r--r--src/buildtool/crypto/hasher.cpp14
-rw-r--r--src/buildtool/crypto/hasher.hpp104
16 files changed, 150 insertions, 350 deletions
diff --git a/src/buildtool/build_engine/expression/expression.cpp b/src/buildtool/build_engine/expression/expression.cpp
index 91d293bc..6ae9bd87 100644
--- a/src/buildtool/build_engine/expression/expression.cpp
+++ b/src/buildtool/build_engine/expression/expression.cpp
@@ -239,12 +239,7 @@ auto Expression::ComputeHash() const noexcept -> std::string {
hasher.Update(el.second->ToHash());
}
}
- auto digest = std::move(hasher).Finalize();
- if (not digest) {
- Logger::Log(LogLevel::Error, "Failed to finalize hash.");
- std::terminate();
- }
- hash = digest->Bytes();
+ hash = std::move(hasher).Finalize().Bytes();
}
return hash;
}
diff --git a/src/buildtool/build_engine/target_map/utils.cpp b/src/buildtool/build_engine/target_map/utils.cpp
index 136727bc..9a8622e4 100644
--- a/src/buildtool/build_engine/target_map/utils.cpp
+++ b/src/buildtool/build_engine/target_map/utils.cpp
@@ -169,12 +169,7 @@ auto hash_vector(std::vector<std::string> const& vec) -> std::string {
for (auto const& s : vec) {
hasher.Update(HashFunction::ComputeHash(s).Bytes());
}
- auto digest = std::move(hasher).Finalize();
- if (not digest) {
- Logger::Log(LogLevel::Error, "Failed to finalize hash.");
- std::terminate();
- }
- return digest->Bytes();
+ return std::move(hasher).Finalize().Bytes();
}
} // namespace
@@ -196,12 +191,7 @@ auto BuildMaps::Target::Utils::createAction(
hasher.Update(no_cache ? std::string{"N"} : std::string{"Y"});
hasher.Update(inputs_exp->ToHash());
- auto digest = std::move(hasher).Finalize();
- if (not digest) {
- Logger::Log(LogLevel::Error, "Failed to finalize hash.");
- std::terminate();
- }
- auto action_id = digest->HexString();
+ auto action_id = std::move(hasher).Finalize().HexString();
std::map<std::string, std::string> env_vars{};
for (auto const& [env_var, env_value] : env->Map()) {
diff --git a/src/buildtool/crypto/TARGETS b/src/buildtool/crypto/TARGETS
index c48bf596..5f72452a 100644
--- a/src/buildtool/crypto/TARGETS
+++ b/src/buildtool/crypto/TARGETS
@@ -1,38 +1,20 @@
-{ "hash_impl":
+{ "hasher":
{ "type": ["@", "rules", "CC", "library"]
- , "name": ["hash_impl"]
- , "hdrs":
- [ "hash_impl.hpp"
- , "hash_impl_md5.hpp"
- , "hash_impl_sha1.hpp"
- , "hash_impl_sha256.hpp"
- , "hash_impl_git.hpp"
- ]
- , "srcs":
- [ "hash_impl_md5.cpp"
- , "hash_impl_sha1.cpp"
- , "hash_impl_sha256.cpp"
- , "hash_impl_git.cpp"
- ]
+ , "name": ["hasher"]
+ , "hdrs": ["hasher.hpp", "hash_impl_sha1.hpp", "hash_impl_sha256.hpp"]
+ , "srcs": ["hasher.cpp", "hash_impl_sha1.cpp", "hash_impl_sha256.cpp"]
+ , "stage": ["src", "buildtool", "crypto"]
, "deps":
[ ["src/buildtool/logging", "logging"]
, ["src/utils/cpp", "hex_string"]
, ["@", "ssl", "", "crypto"]
]
- , "stage": ["src", "buildtool", "crypto"]
- }
-, "hash_generator":
- { "type": ["@", "rules", "CC", "library"]
- , "name": ["hash_generator"]
- , "hdrs": ["hash_generator.hpp"]
- , "deps": ["hash_impl"]
- , "stage": ["src", "buildtool", "crypto"]
}
, "hash_function":
{ "type": ["@", "rules", "CC", "library"]
, "name": ["hash_function"]
, "hdrs": ["hash_function.hpp"]
- , "deps": ["hash_generator"]
+ , "deps": ["hasher"]
, "stage": ["src", "buildtool", "crypto"]
}
}
diff --git a/src/buildtool/crypto/hash_function.hpp b/src/buildtool/crypto/hash_function.hpp
index 4030c7a7..734a096d 100644
--- a/src/buildtool/crypto/hash_function.hpp
+++ b/src/buildtool/crypto/hash_function.hpp
@@ -6,7 +6,7 @@
#include <optional>
#include <string>
-#include "src/buildtool/crypto/hash_generator.hpp"
+#include "src/buildtool/crypto/hasher.hpp"
/// \brief Hash function used for the entire buildtool.
class HashFunction {
@@ -23,13 +23,13 @@ class HashFunction {
/// \brief Compute a plain hash.
[[nodiscard]] static auto ComputeHash(std::string const& data) noexcept
- -> HashGenerator::HashDigest {
+ -> Hasher::HashDigest {
return ComputeTaggedHash(data);
}
/// \brief Compute a blob hash.
[[nodiscard]] static auto ComputeBlobHash(std::string const& data) noexcept
- -> HashGenerator::HashDigest {
+ -> Hasher::HashDigest {
static auto const kBlobTagCreator =
[](std::string const& data) -> std::string {
return {"blob " + std::to_string(data.size()) + '\0'};
@@ -39,7 +39,7 @@ class HashFunction {
/// \brief Compute a tree hash.
[[nodiscard]] static auto ComputeTreeHash(std::string const& data) noexcept
- -> HashGenerator::HashDigest {
+ -> Hasher::HashDigest {
static auto const kTreeTagCreator =
[](std::string const& data) -> std::string {
return {"tree " + std::to_string(data.size()) + '\0'};
@@ -48,14 +48,12 @@ class HashFunction {
}
/// \brief Obtain incremental hasher for computing plain hashes.
- [[nodiscard]] static auto Hasher() noexcept -> HashGenerator::Hasher {
+ [[nodiscard]] static auto Hasher() noexcept -> ::Hasher {
switch (HashType()) {
case JustHash::Native:
- return HashGenerator{HashGenerator::HashType::SHA1}
- .IncrementalHasher();
+ return ::Hasher{Hasher::HashType::SHA1};
case JustHash::Compatible:
- return HashGenerator{HashGenerator::HashType::SHA256}
- .IncrementalHasher();
+ return ::Hasher{Hasher::HashType::SHA256};
}
}
@@ -74,13 +72,13 @@ class HashFunction {
[[nodiscard]] static auto ComputeTaggedHash(
std::string const& data,
std::function<std::string(std::string const&)> const& tag_creator =
- {}) noexcept -> HashGenerator::HashDigest {
+ {}) noexcept -> Hasher::HashDigest {
auto hasher = Hasher();
if (tag_creator and HashType() == JustHash::Native) {
hasher.Update(tag_creator(data));
}
hasher.Update(data);
- return *std::move(hasher).Finalize();
+ return std::move(hasher).Finalize();
}
};
diff --git a/src/buildtool/crypto/hash_generator.hpp b/src/buildtool/crypto/hash_generator.hpp
deleted file mode 100644
index d8b59631..00000000
--- a/src/buildtool/crypto/hash_generator.hpp
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_GENERATOR_HPP
-#define INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_GENERATOR_HPP
-
-#include <iomanip>
-#include <memory>
-#include <optional>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "src/buildtool/crypto/hash_impl_git.hpp"
-#include "src/buildtool/crypto/hash_impl_md5.hpp"
-#include "src/buildtool/crypto/hash_impl_sha1.hpp"
-#include "src/buildtool/crypto/hash_impl_sha256.hpp"
-#include "src/utils/cpp/hex_string.hpp"
-
-/// \brief Hash generator, supports multiple types \ref HashType.
-class HashGenerator {
- public:
- /// \brief Types of hash implementations supported by generator.
- enum class HashType { MD5, SHA1, SHA256, GIT };
-
- /// \brief The universal hash digest.
- /// The type of hash and the digest length depends on the hash
- /// implementation used to generated this digest.
- class HashDigest {
- friend HashGenerator;
-
- public:
- /// \brief Get pointer to raw bytes of digest.
- /// Length can be obtained using \ref Length.
- [[nodiscard]] auto Bytes() const& -> std::string const& {
- return bytes_;
- }
-
- [[nodiscard]] auto Bytes() && -> std::string {
- return std::move(bytes_);
- }
-
- /// \brief Get hexadecimal string of digest.
- /// Length is twice the length of raw bytes (\ref Length).
- [[nodiscard]] auto HexString() const -> std::string {
- return ToHexString(bytes_);
- }
-
- /// \brief Get digest length in raw bytes.
- [[nodiscard]] auto Length() const -> std::size_t {
- return bytes_.size();
- }
-
- private:
- std::string bytes_{};
-
- explicit HashDigest(std::string bytes) : bytes_{std::move(bytes)} {}
- };
-
- /// \brief Incremental hasher.
- class Hasher {
- friend HashGenerator;
-
- public:
- /// \brief Feed data to the hasher.
- auto Update(std::string const& data) noexcept -> bool {
- return impl_->Update(data);
- }
-
- /// \brief Finalize hash.
- [[nodiscard]] auto Finalize() && noexcept -> std::optional<HashDigest> {
- auto hash = std::move(*impl_).Finalize();
- if (hash) {
- return HashDigest{*hash};
- }
- return std::nullopt;
- }
-
- private:
- std::unique_ptr<IHashImpl> impl_;
-
- explicit Hasher(std::unique_ptr<IHashImpl> impl)
- : impl_{std::move(impl)} {}
- };
-
- /// \brief Create hash generator for specific type.
- explicit HashGenerator(HashType type)
- : type_{type}, digest_length_{create_impl()->DigestLength()} {}
- HashGenerator(HashGenerator const&) = delete;
- HashGenerator(HashGenerator&&) = delete;
- auto operator=(HashGenerator const&) -> HashGenerator& = delete;
- auto operator=(HashGenerator&&) -> HashGenerator& = delete;
- ~HashGenerator() noexcept = default;
-
- /// \brief Run hash function on data.
- [[nodiscard]] auto Run(std::string const& data) const noexcept
- -> HashDigest {
- auto impl = create_impl();
- return HashDigest{std::move(*impl).Compute(data)};
- }
-
- [[nodiscard]] auto IncrementalHasher() const noexcept -> Hasher {
- return Hasher(create_impl());
- }
-
- [[nodiscard]] auto DigestLength() const noexcept -> std::size_t {
- return digest_length_;
- }
-
- private:
- HashType type_{};
- std::size_t digest_length_{};
-
- /// \brief Dispatch for creating the actual implementation
- [[nodiscard]] auto create_impl() const noexcept
- -> std::unique_ptr<IHashImpl> {
- switch (type_) {
- case HashType::MD5:
- return CreateHashImplMd5();
- case HashType::SHA1:
- return CreateHashImplSha1();
- case HashType::SHA256:
- return CreateHashImplSha256();
- case HashType::GIT:
- return CreateHashImplGit();
- }
- }
-};
-
-#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_GENERATOR_HPP
diff --git a/src/buildtool/crypto/hash_impl.hpp b/src/buildtool/crypto/hash_impl.hpp
deleted file mode 100644
index d37322bd..00000000
--- a/src/buildtool/crypto/hash_impl.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_HPP
-#define INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_HPP
-
-#include <optional>
-#include <string>
-
-#include "src/buildtool/logging/logger.hpp"
-
-/// \brief Interface for hash implementations
-class IHashImpl {
- public:
- IHashImpl() noexcept = default;
- IHashImpl(IHashImpl const&) = default;
- IHashImpl(IHashImpl&&) = default;
- auto operator=(IHashImpl const&) -> IHashImpl& = default;
- auto operator=(IHashImpl&&) -> IHashImpl& = default;
- virtual ~IHashImpl() = default;
-
- /// \brief Feed data to the incremental hashing.
- [[nodiscard]] virtual auto Update(std::string const& data) noexcept
- -> bool = 0;
-
- /// \brief Finalize the hashing and return hash as string of raw bytes.
- [[nodiscard]] virtual auto Finalize() && noexcept
- -> std::optional<std::string> = 0;
-
- /// \brief Compute the hash of data and return it as string of raw bytes.
- [[nodiscard]] virtual auto Compute(std::string const& data) && noexcept
- -> std::string = 0;
-
- /// \brief Get length of the hash in raw bytes.
- [[nodiscard]] virtual auto DigestLength() const noexcept -> std::size_t = 0;
-
- static auto FatalError() noexcept -> void {
- Logger::Log(LogLevel::Error, "Failed to compute hash.");
- std::terminate();
- }
-};
-
-#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_HPP
diff --git a/src/buildtool/crypto/hash_impl_git.cpp b/src/buildtool/crypto/hash_impl_git.cpp
deleted file mode 100644
index 9cb2a761..00000000
--- a/src/buildtool/crypto/hash_impl_git.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <array>
-#include <cstdint>
-
-#include "openssl/sha.h"
-#include "src/buildtool/crypto/hash_impl.hpp"
-
-/// \brief Hash implementation for Git blob ids.
-/// Does not support incremental hashing.
-class HashImplGit final : public IHashImpl {
- public:
- auto Update(std::string const& /*data*/) noexcept -> bool final {
- return false;
- }
-
- auto Finalize() && noexcept -> std::optional<std::string> final {
- return std::nullopt;
- }
-
- auto Compute(std::string const& data) && noexcept -> std::string final {
- SHA_CTX ctx;
- std::string const header{"blob " + std::to_string(data.size()) + '\0'};
- if (SHA1_Init(&ctx) == 1 &&
- SHA1_Update(&ctx, header.data(), header.size()) == 1 &&
- SHA1_Update(&ctx, data.data(), data.size()) == 1) {
- auto out = std::array<std::uint8_t, SHA_DIGEST_LENGTH>{};
- if (SHA1_Final(out.data(), &ctx) == 1) {
- return std::string{out.begin(), out.end()};
- }
- }
- FatalError();
- return {};
- }
-
- [[nodiscard]] auto DigestLength() const noexcept -> std::size_t final {
- return SHA_DIGEST_LENGTH;
- }
-};
-
-/// \brief Factory for Git implementation
-auto CreateHashImplGit() -> std::unique_ptr<IHashImpl> {
- return std::make_unique<HashImplGit>();
-}
diff --git a/src/buildtool/crypto/hash_impl_git.hpp b/src/buildtool/crypto/hash_impl_git.hpp
deleted file mode 100644
index be0738da..00000000
--- a/src/buildtool/crypto/hash_impl_git.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_GIT_HPP
-#define INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_GIT_HPP
-
-#include <memory>
-
-#include "src/buildtool/crypto/hash_impl.hpp"
-
-[[nodiscard]] extern auto CreateHashImplGit() -> std::unique_ptr<IHashImpl>;
-
-#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_GIT_HPP
diff --git a/src/buildtool/crypto/hash_impl_md5.cpp b/src/buildtool/crypto/hash_impl_md5.cpp
deleted file mode 100644
index 106dc984..00000000
--- a/src/buildtool/crypto/hash_impl_md5.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <array>
-#include <cstdint>
-
-#include "openssl/md5.h"
-#include "src/buildtool/crypto/hash_impl.hpp"
-
-/// \brief Hash implementation for MD5
-class HashImplMd5 final : public IHashImpl {
- public:
- HashImplMd5() { initialized_ = MD5_Init(&ctx_) == 1; }
-
- auto Update(std::string const& data) noexcept -> bool final {
- return initialized_ and
- MD5_Update(&ctx_, data.data(), data.size()) == 1;
- }
-
- auto Finalize() && noexcept -> std::optional<std::string> final {
- if (initialized_) {
- auto out = std::array<std::uint8_t, MD5_DIGEST_LENGTH>{};
- if (MD5_Final(out.data(), &ctx_) == 1) {
- return std::string{out.begin(), out.end()};
- }
- }
- return std::nullopt;
- }
-
- auto Compute(std::string const& data) && noexcept -> std::string final {
- if (Update(data)) {
- auto digest = std::move(*this).Finalize();
- if (digest) {
- return *digest;
- }
- }
- FatalError();
- return {};
- }
-
- [[nodiscard]] auto DigestLength() const noexcept -> std::size_t final {
- return MD5_DIGEST_LENGTH;
- }
-
- private:
- MD5_CTX ctx_{};
- bool initialized_{};
-};
-
-/// \brief Factory for MD5 implementation
-auto CreateHashImplMd5() -> std::unique_ptr<IHashImpl> {
- return std::make_unique<HashImplMd5>();
-}
diff --git a/src/buildtool/crypto/hash_impl_md5.hpp b/src/buildtool/crypto/hash_impl_md5.hpp
deleted file mode 100644
index 95411570..00000000
--- a/src/buildtool/crypto/hash_impl_md5.hpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_MD5_HPP
-#define INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_MD5_HPP
-
-#include <memory>
-
-#include "src/buildtool/crypto/hash_impl.hpp"
-
-[[nodiscard]] extern auto CreateHashImplMd5() -> std::unique_ptr<IHashImpl>;
-
-#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_MD5_HPP
diff --git a/src/buildtool/crypto/hash_impl_sha1.cpp b/src/buildtool/crypto/hash_impl_sha1.cpp
index e0bee0fb..cecad9ca 100644
--- a/src/buildtool/crypto/hash_impl_sha1.cpp
+++ b/src/buildtool/crypto/hash_impl_sha1.cpp
@@ -1,11 +1,12 @@
+#include "src/buildtool/crypto/hash_impl_sha1.hpp"
+
#include <array>
#include <cstdint>
#include "openssl/sha.h"
-#include "src/buildtool/crypto/hash_impl.hpp"
/// \brief Hash implementation for SHA-1
-class HashImplSha1 final : public IHashImpl {
+class HashImplSha1 final : public Hasher::IHashImpl {
public:
HashImplSha1() { initialized_ = SHA1_Init(&ctx_) == 1; }
@@ -35,16 +36,12 @@ class HashImplSha1 final : public IHashImpl {
return {};
}
- [[nodiscard]] auto DigestLength() const noexcept -> std::size_t final {
- return SHA_DIGEST_LENGTH;
- }
-
private:
SHA_CTX ctx_{};
bool initialized_{};
};
/// \brief Factory for SHA-1 implementation
-auto CreateHashImplSha1() -> std::unique_ptr<IHashImpl> {
+auto CreateHashImplSha1() -> std::unique_ptr<Hasher::IHashImpl> {
return std::make_unique<HashImplSha1>();
}
diff --git a/src/buildtool/crypto/hash_impl_sha1.hpp b/src/buildtool/crypto/hash_impl_sha1.hpp
index 7b8196b5..b82edd64 100644
--- a/src/buildtool/crypto/hash_impl_sha1.hpp
+++ b/src/buildtool/crypto/hash_impl_sha1.hpp
@@ -3,8 +3,9 @@
#include <memory>
-#include "src/buildtool/crypto/hash_impl.hpp"
+#include "src/buildtool/crypto/hasher.hpp"
-[[nodiscard]] extern auto CreateHashImplSha1() -> std::unique_ptr<IHashImpl>;
+[[nodiscard]] extern auto CreateHashImplSha1()
+ -> std::unique_ptr<Hasher::IHashImpl>;
#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_SHA1_HPP
diff --git a/src/buildtool/crypto/hash_impl_sha256.cpp b/src/buildtool/crypto/hash_impl_sha256.cpp
index bbea10d3..8fa80bbc 100644
--- a/src/buildtool/crypto/hash_impl_sha256.cpp
+++ b/src/buildtool/crypto/hash_impl_sha256.cpp
@@ -1,11 +1,12 @@
+#include "src/buildtool/crypto/hash_impl_sha256.hpp"
+
#include <array>
#include <cstdint>
#include "openssl/sha.h"
-#include "src/buildtool/crypto/hash_impl.hpp"
/// \brief Hash implementation for SHA-256
-class HashImplSha256 final : public IHashImpl {
+class HashImplSha256 final : public Hasher::IHashImpl {
public:
HashImplSha256() { initialized_ = SHA256_Init(&ctx_) == 1; }
@@ -35,16 +36,12 @@ class HashImplSha256 final : public IHashImpl {
return {};
}
- [[nodiscard]] auto DigestLength() const noexcept -> std::size_t final {
- return SHA256_DIGEST_LENGTH;
- }
-
private:
SHA256_CTX ctx_{};
bool initialized_{};
};
/// \brief Factory for SHA-256 implementation
-auto CreateHashImplSha256() -> std::unique_ptr<IHashImpl> {
+auto CreateHashImplSha256() -> std::unique_ptr<Hasher::IHashImpl> {
return std::make_unique<HashImplSha256>();
}
diff --git a/src/buildtool/crypto/hash_impl_sha256.hpp b/src/buildtool/crypto/hash_impl_sha256.hpp
index d74c1492..106d8a0b 100644
--- a/src/buildtool/crypto/hash_impl_sha256.hpp
+++ b/src/buildtool/crypto/hash_impl_sha256.hpp
@@ -3,8 +3,9 @@
#include <memory>
-#include "src/buildtool/crypto/hash_impl.hpp"
+#include "src/buildtool/crypto/hasher.hpp"
-[[nodiscard]] extern auto CreateHashImplSha256() -> std::unique_ptr<IHashImpl>;
+[[nodiscard]] extern auto CreateHashImplSha256()
+ -> std::unique_ptr<Hasher::IHashImpl>;
#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASH_IMPL_SHA256_HPP
diff --git a/src/buildtool/crypto/hasher.cpp b/src/buildtool/crypto/hasher.cpp
new file mode 100644
index 00000000..6f432679
--- /dev/null
+++ b/src/buildtool/crypto/hasher.cpp
@@ -0,0 +1,14 @@
+#include "src/buildtool/crypto/hasher.hpp"
+
+#include "src/buildtool/crypto/hash_impl_sha1.hpp"
+#include "src/buildtool/crypto/hash_impl_sha256.hpp"
+
+auto Hasher::CreateHashImpl(HashType type) noexcept
+ -> std::unique_ptr<IHashImpl> {
+ switch (type) {
+ case HashType::SHA1:
+ return CreateHashImplSha1();
+ case HashType::SHA256:
+ return CreateHashImplSha256();
+ }
+}
diff --git a/src/buildtool/crypto/hasher.hpp b/src/buildtool/crypto/hasher.hpp
new file mode 100644
index 00000000..0efe300f
--- /dev/null
+++ b/src/buildtool/crypto/hasher.hpp
@@ -0,0 +1,104 @@
+#ifndef INCLUDED_SRC_BUILDTOOL_CRYPTO_HASHER_HPP
+#define INCLUDED_SRC_BUILDTOOL_CRYPTO_HASHER_HPP
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+
+#include "src/buildtool/logging/logger.hpp"
+#include "src/utils/cpp/hex_string.hpp"
+
+/// \brief Incremental hasher.
+class Hasher {
+ public:
+ /// \brief Types of hash implementations supported by generator.
+ enum class HashType : std::uint8_t { SHA1, SHA256 };
+
+ /// \brief The universal hash digest.
+ /// The type of hash and the digest length depends on the hash
+ /// implementation used to generated this digest.
+ class HashDigest {
+ friend Hasher;
+
+ public:
+ /// \brief Get pointer to raw bytes of digest.
+ /// Length can be obtained using \ref Length.
+ [[nodiscard]] auto Bytes() const& -> std::string const& {
+ return bytes_;
+ }
+
+ [[nodiscard]] auto Bytes() && -> std::string {
+ return std::move(bytes_);
+ }
+
+ /// \brief Get hexadecimal string of digest.
+ /// Length is twice the length of raw bytes (\ref Length).
+ [[nodiscard]] auto HexString() const -> std::string {
+ return ToHexString(bytes_);
+ }
+
+ /// \brief Get digest length in raw bytes.
+ [[nodiscard]] auto Length() const -> std::size_t {
+ return bytes_.size();
+ }
+
+ private:
+ std::string bytes_{};
+
+ explicit HashDigest(std::string bytes) : bytes_{std::move(bytes)} {}
+ };
+
+ /// \brief Interface for hash implementations
+ class IHashImpl {
+ public:
+ IHashImpl() noexcept = default;
+ IHashImpl(IHashImpl const&) = delete;
+ IHashImpl(IHashImpl&&) = default;
+ auto operator=(IHashImpl const&) -> IHashImpl& = delete;
+ auto operator=(IHashImpl&&) -> IHashImpl& = default;
+ virtual ~IHashImpl() = default;
+
+ /// \brief Feed data to the incremental hashing.
+ [[nodiscard]] virtual auto Update(std::string const& data) noexcept
+ -> bool = 0;
+
+ /// \brief Finalize the hashing and return hash as string of raw bytes.
+ [[nodiscard]] virtual auto Finalize() && noexcept
+ -> std::optional<std::string> = 0;
+
+ /// \brief Compute the hash of data and return it as string of raw
+ /// bytes.
+ [[nodiscard]] virtual auto Compute(std::string const& data) && noexcept
+ -> std::string = 0;
+
+ static auto FatalError() noexcept -> void {
+ Logger::Log(LogLevel::Error, "Failed to compute hash.");
+ std::terminate();
+ }
+ };
+
+ explicit Hasher(HashType type) : impl_{CreateHashImpl(type)} {}
+
+ /// \brief Feed data to the hasher.
+ auto Update(std::string const& data) noexcept -> bool {
+ return impl_->Update(data);
+ }
+
+ /// \brief Finalize hash.
+ [[nodiscard]] auto Finalize() && noexcept -> HashDigest {
+ if (auto hash = std::move(*impl_).Finalize()) {
+ return HashDigest{std::move(*hash)};
+ }
+ IHashImpl::FatalError();
+ return HashDigest{{}};
+ }
+
+ private:
+ std::unique_ptr<IHashImpl> impl_;
+
+ [[nodiscard]] static auto CreateHashImpl(HashType type) noexcept
+ -> std::unique_ptr<IHashImpl>;
+};
+
+#endif // INCLUDED_SRC_BUILDTOOL_CRYPTO_HASHER_HPP