20 #ifndef CS_CRYPTO_HASH_DIGEST_H
21 #define CS_CRYPTO_HASH_DIGEST_H
23 #include <core/hash/hash_append.h>
24 #include <util/tools/crypto_traits.h>
27 #include <type_traits>
29 namespace cs_crypto::hash {
32 using finalize_member_fn =
decltype(std::declval<T&&>().finalize());
35 using finalize_free_fn =
decltype(finalize(std::declval<T&&>()));
38 using make_context_fn =
decltype(T::make_context());
40 struct finalize_dispatch_fn {
41 template <
typename HashContext>
42 auto operator()(HashContext &&ctx)
const
44 if constexpr (traits::is_detected<finalize_member_fn, HashContext>{}) {
45 return std::move(ctx).finalize();
47 }
else if constexpr (traits::is_detected<finalize_free_fn, HashContext>{}) {
48 return finalize(std::move(ctx));
51 static_assert(traits::always_false<HashContext>{},
52 "Driver incomplete, unable to locate finalize() method or free function");
57 inline constexpr finalize_dispatch_fn finalize{};
59 template <
typename Ctx>
60 [[maybe_unused]]
constexpr static bool is_hash_digest_context_v =
61 is_appendable_hash_context_v<Ctx> &&
62 traits::is_detected_v<make_context_fn, Ctx> &&
63 (traits::is_detected_v<finalize_free_fn, Ctx> || traits::is_detected_v<finalize_member_fn, Ctx>);
65 template <
typename HashContext>
66 struct hash_digest_internal {
67 using result_type = std::optional<cs_crypto::traits::remove_optional_t<
decltype(finalize(std::declval<HashContext &&>()))>>;
69 template <
typename... Ts>
70 constexpr auto operator()(Ts &&... args)
const -> result_type
72 static_assert(! std::is_same_v<HashContext, cs_crypto::traits::nonesuch>,
73 "Selected driver does not support this operation");
75 static_assert(is_hash_digest_context_v<HashContext>,
76 "Hash context does not satisfy is_hash_digest_context_v type trait");
78 auto maybe_context = HashContext::make_context();
79 if (! maybe_context.has_value()) {
83 auto ctx = std::move(maybe_context).value();
84 hash_append(ctx, std::forward<Ts>(args)...);
86 return finalize(std::move(ctx));
90 template <
typename HashDriver,
template <
typename>
typename HashSelector>
91 inline constexpr hash_digest_internal<HashSelector<HashDriver>> hash_digest = {};