9#ifndef BOTAN_STL_UTIL_H_
10#define BOTAN_STL_UTIL_H_
23#include <botan/concepts.h>
24#include <botan/secmem.h>
25#include <botan/strong_type.h>
29template <concepts::contiguous_container T = std::vector<u
int8_t>>
31 return T(s.cbegin(), s.cend());
34inline std::string
to_string(std::span<const uint8_t> bytes) {
35 return std::string(bytes.begin(), bytes.end());
47template <
typename RetT,
typename KeyT,
typename ReducerT>
48RetT
reduce(
const std::vector<KeyT>& keys, RetT acc, ReducerT reducer)
49 requires std::is_convertible_v<ReducerT, std::function<RetT(RetT,
const KeyT&)>>
51 for(
const KeyT& key : keys) {
52 acc = reducer(std::move(acc), key);
60template <
typename K,
typename V>
72template <
typename K,
typename V>
88template <
typename K,
typename V>
89inline V
search_map(
const std::map<K, V>& mapping,
const K& key,
const V& null_result = V()) {
90 auto i = mapping.find(key);
91 if(i == mapping.end()) {
97template <
typename K,
typename V,
typename R>
98inline R
search_map(
const std::map<K, V>& mapping,
const K& key,
const R& null_result,
const R& found_result) {
99 auto i = mapping.find(key);
100 if(i == mapping.end()) {
109template <
typename K,
typename V>
111 multimap.insert(std::make_pair(key, value));
117template <
typename T,
typename OT>
119 for(
size_t i = 0; i != vec.size(); ++i) {
127template <
typename T,
typename Pred>
129 auto i = assoc.begin();
130 while(i != assoc.end()) {
146 template <concepts::contiguous_container ContainerT>
147 auto copy(
const size_t count) {
148 const auto result =
take(count);
149 return ContainerT(result.begin(), result.end());
152 auto copy_as_vector(
const size_t count) {
return copy<std::vector<uint8_t>>(count); }
156 std::span<const uint8_t>
take(
const size_t count) {
158 auto result = m_remaining.first(count);
159 m_remaining = m_remaining.subspan(count);
163 template <
size_t count>
164 std::span<const uint8_t, count>
take() {
166 auto result = m_remaining.first<count>();
167 m_remaining = m_remaining.subspan(count);
171 template <concepts::contiguous_strong_type T>
179 const auto data =
take(sink.size());
180 std::copy(data.begin(), data.end(), sink.begin());
187 bool empty()
const {
return m_remaining.empty(); }
190 std::span<const uint8_t> m_remaining;
208 constexpr std::span<uint8_t>
next(
size_t bytes) {
211 auto result = m_buffer.first(bytes);
212 m_buffer = m_buffer.subspan(bytes);
216 template <
size_t bytes>
217 constexpr std::span<uint8_t, bytes>
next() {
220 auto result = m_buffer.first<bytes>();
221 m_buffer = m_buffer.subspan(bytes);
225 template <concepts::contiguous_strong_type StrongT>
235 constexpr void append(std::span<const uint8_t> buffer) {
236 auto sink =
next(buffer.size());
237 std::copy(buffer.begin(), buffer.end(), sink.begin());
240 constexpr void append(uint8_t b,
size_t repeat = 1) {
241 auto sink =
next(repeat);
242 std::fill(sink.begin(), sink.end(), b);
245 constexpr bool full()
const {
return m_buffer.empty(); }
250 std::span<uint8_t> m_buffer;
257template <
typename... Ts>
259 static_assert(
sizeof...(buffers) > 0,
"concat requires at least one buffer");
261 using result_t = std::remove_cvref_t<std::tuple_element_t<0, std::tuple<Ts...>>>;
263 result.reserve((buffers.size() + ...));
264 (result.insert(result.end(), buffers.begin(), buffers.end()), ...);
273template <
typename ResultT,
typename... Ts>
275 return concat(ResultT(), std::forward<Ts>(buffers)...);
278template <
typename... Alts,
typename... Ts>
280 return (std::holds_alternative<Alts>(v) || ...);
283template <
typename GeneralVariantT,
typename SpecialT>
285 return std::is_constructible_v<GeneralVariantT, SpecialT>;
288template <
typename GeneralVariantT,
typename... SpecialTs>
290 return (std::is_constructible_v<GeneralVariantT, SpecialTs> && ...);
300template <
typename GeneralVariantT,
typename SpecialT>
302 requires(std::is_constructible_v<GeneralVariantT, std::decay_t<SpecialT>>)
304 return std::forward<SpecialT>(specific);
314template <
typename GeneralVariantT,
typename... SpecialTs>
315constexpr GeneralVariantT
generalize_to(std::variant<SpecialTs...> specific)
noexcept {
317 is_generalizable_to<GeneralVariantT>(specific),
318 "Desired general type must be implicitly constructible by all types of the specialized std::variant<>");
319 return std::visit([](
auto s) -> GeneralVariantT {
return s; }, std::move(specific));
324template <
class... Ts>
326 using Ts::operator()...;
329template <
class... Ts>
339template <std::invocable FunT>
350 if(m_cleanup.has_value()) {
361 std::optional<FunT> m_cleanup;
#define BOTAN_STATE_CHECK(expr)
void skip(const size_t count)
auto copy_as_secure_vector(const size_t count)
void copy_into(std::span< uint8_t > sink)
BufferSlicer(std::span< const uint8_t > buffer)
std::span< const uint8_t, count > take()
auto copy(const size_t count)
std::span< const uint8_t > take(const size_t count)
StrongSpan< const T > take(const size_t count)
auto copy_as_vector(const size_t count)
Helper class to ease in-place marshalling of concatenated fixed-length values.
constexpr void append(std::span< const uint8_t > buffer)
constexpr void append(uint8_t b, size_t repeat=1)
constexpr size_t remaining_capacity() const
StrongSpan< StrongT > next(size_t bytes)
constexpr std::span< uint8_t > next(size_t bytes)
constexpr std::span< uint8_t, bytes > next()
constexpr uint8_t & next_byte()
constexpr BufferStuffer(std::span< uint8_t > buffer)
constexpr bool full() const
Helper class to create a RAII-style cleanup callback.
scoped_cleanup(const scoped_cleanup &)=delete
scoped_cleanup & operator=(const scoped_cleanup &)=delete
scoped_cleanup & operator=(scoped_cleanup &&)=delete
scoped_cleanup(FunT cleanup)
scoped_cleanup(scoped_cleanup &&)=delete
int(* final)(unsigned char *, CTX *)
constexpr GeneralVariantT generalize_to(SpecialT &&specific) noexcept
Converts a given variant into another variant-ish whose type states are a super set of the given vari...
void map_remove_if(Pred pred, T &assoc)
T to_byte_vector(std::string_view s)
ResultT concat_as(Ts &&... buffers)
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
RetT reduce(const std::vector< KeyT > &keys, RetT acc, ReducerT reducer)
std::set< K > map_keys_as_set(const std::map< K, V > &kv)
V search_map(const std::map< K, V > &mapping, const K &key, const V &null_result=V())
void multimap_insert(std::multimap< K, V > &multimap, const K &key, const V &value)
bool value_exists(const std::vector< T > &vec, const OT &val)
constexpr bool is_generalizable_to(const SpecialT &) noexcept
std::string to_string(ErrorType type)
Convert an ErrorType to string.
decltype(auto) concat(Ts &&... buffers)
overloaded(Ts...) -> overloaded< Ts... >