20 #ifndef CS_CRYPTO_SYM_PROCESS_MSG_H
21 #define CS_CRYPTO_SYM_PROCESS_MSG_H
23 #include <util/conversions/byte.h>
24 #include <util/tools/crypto_traits.h>
25 #include <util/tools/is_detected_traits.h>
26 #include <util/tools/span.h>
30 #include <type_traits>
33 namespace cs_crypto::cipher {
36 using update_member_fn =
decltype(std::declval<T &>().update(std::declval<cs_crypto::util::span<std::byte>>()));
39 using update_free_fn =
decltype(update(std::declval<T &>(), std::declval<cs_crypto::util::span<std::byte>>()));
41 struct update_dispatch_internal
43 template <
typename CipherContext>
constexpr auto operator()(CipherContext &ctx, cs_crypto::util::span<std::byte> bytes)
const
45 if constexpr (cs_crypto::traits::is_detected_v<update_member_fn, CipherContext>) {
46 return ctx.update(bytes);
48 }
else if constexpr (cs_crypto::traits::is_detected_v<update_free_fn, CipherContext>) {
49 return update(ctx, bytes);
52 static_assert(cs_crypto::traits::always_false<CipherContext>{},
53 "Driver incomplete, unable to locate update() as a method or free function");
58 inline constexpr update_dispatch_internal dispatch_update{};
60 template <
typename CipherContext,
typename T,
61 typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
62 constexpr auto internal_cipher_append(CipherContext &ctx,
const T v)
64 return dispatch_update(ctx, {util::to_byte_ptr(std::addressof(v)), 1});
67 template <
typename CipherContext,
typename T, std::size_t N,
68 typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
69 constexpr auto internal_cipher_append(CipherContext &ctx,
const T (&arr)[N])
71 return dispatch_update(ctx, {util::to_byte_ptr(std::addressof(arr[0])), N});
74 template <
typename CipherContext,
typename T, std::size_t N,
75 typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
76 constexpr auto internal_cipher_append(CipherContext &ctx,
const std::array<T, N> &data)
78 return dispatch_update(ctx, {util::to_byte_ptr(data.data()), data.size()});
81 template <
typename CipherContext,
typename T,
82 typename = std::enable_if_t<cs_crypto::traits::is_uniquely_represented_byte_v<T>>>
83 constexpr auto internal_cipher_append(CipherContext &ctx,
const std::vector<T> &data)
85 return dispatch_update(ctx, {util::to_byte_ptr(data.data()), data.size()});
88 template <
typename CipherContext>
89 constexpr auto internal_cipher_append(CipherContext &ctx,
const std::string &s)
91 return dispatch_update(ctx, {util::to_byte_ptr(s.data()), s.size()});
94 template <
typename CipherContext,
typename T,
typename = std::enable_if_t<cs_crypto::traits::is_iterable_v<T>>>
95 constexpr auto internal_cipher_append(CipherContext &ctx,
const T &data)
99 for (
const auto elem : data) {
100 internal_cipher_append(ctx, elem);
104 template <
typename CipherContext,
typename It,
typename End>
105 constexpr auto internal_cipher_append(CipherContext &ctx, It iter, End end)
109 while (iter != end) {
110 internal_cipher_append(ctx, *iter);
111 iter = std::next(iter);
115 template <
typename Ctx>
116 [[maybe_unused]]
inline constexpr bool is_appendable_cipher_context_v =
117 std::is_move_assignable_v<Ctx> && std::is_move_constructible_v<Ctx> &&
118 (cs_crypto::traits::is_detected_v<update_free_fn, Ctx> || cs_crypto::traits::is_detected_v<update_member_fn, Ctx>);
120 struct cipher_append_internal
122 template <
typename CipherContext,
typename... Ts>
123 constexpr auto operator()(CipherContext &&context, Ts &&... args)
const
125 static_assert(! std::is_same_v<CipherContext, cs_crypto::traits::nonesuch>,
126 "Driver does not support this operation");
128 static_assert(is_appendable_cipher_context_v<std::remove_reference_t<CipherContext>>,
129 "Cipher context does not satisfy is_appendable_cipher_context type trait");
131 return internal_cipher_append(std::forward<CipherContext>(context), std::forward<Ts>(args)...);
135 inline constexpr const cipher_append_internal cipher_append = {};