/src/Botan-3.4.0/build/include/public/botan/concepts.h
Line | Count | Source |
1 | | /** |
2 | | * Useful concepts that are available throughout the library |
3 | | * (C) 2023 Jack Lloyd |
4 | | * 2023 René Meusel - Rohde & Schwarz Cybersecurity |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | */ |
8 | | |
9 | | #ifndef BOTAN_CONCEPTS_H_ |
10 | | #define BOTAN_CONCEPTS_H_ |
11 | | |
12 | | #include <botan/assert.h> |
13 | | |
14 | | #include <compare> |
15 | | #include <concepts> |
16 | | #include <cstdint> |
17 | | #include <ostream> |
18 | | #include <ranges> |
19 | | #include <span> |
20 | | #include <type_traits> |
21 | | |
22 | | namespace Botan { |
23 | | |
24 | | template <typename T, typename Tag, typename... Capabilities> |
25 | | class Strong; |
26 | | |
27 | | template <typename... Ts> |
28 | | struct is_strong_type : std::false_type {}; |
29 | | |
30 | | template <typename... Ts> |
31 | | struct is_strong_type<Strong<Ts...>> : std::true_type {}; |
32 | | |
33 | | template <typename... Ts> |
34 | | constexpr bool is_strong_type_v = is_strong_type<std::remove_const_t<Ts>...>::value; |
35 | | |
36 | | template <typename T0, typename... Ts> |
37 | | struct all_same { |
38 | | static constexpr bool value = (std::is_same_v<T0, Ts> && ...); |
39 | | }; |
40 | | |
41 | | template <typename... Ts> |
42 | | static constexpr bool all_same_v = all_same<Ts...>::value; |
43 | | |
44 | | namespace ranges { |
45 | | |
46 | | /** |
47 | | * Models a std::ranges::contiguous_range that (optionally) restricts its |
48 | | * value_type to ValueT. In other words: a stretch of contiguous memory of |
49 | | * a certain type (optional ValueT). |
50 | | */ |
51 | | template <typename T, typename ValueT = std::ranges::range_value_t<T>> |
52 | | concept contiguous_range = std::ranges::contiguous_range<T> && std::same_as<ValueT, std::ranges::range_value_t<T>>; |
53 | | |
54 | | /** |
55 | | * Models a std::ranges::contiguous_range that satisfies |
56 | | * std::ranges::output_range with an arbitrary value_type. In other words: a |
57 | | * stretch of contiguous memory of a certain type (optional ValueT) that can be |
58 | | * written to. |
59 | | */ |
60 | | template <typename T, typename ValueT = std::ranges::range_value_t<T>> |
61 | | concept contiguous_output_range = contiguous_range<T, ValueT> && std::ranges::output_range<T, ValueT>; |
62 | | |
63 | | /** |
64 | | * Models a range that can be turned into a std::span<>. Typically, this is some |
65 | | * form of ranges::contiguous_range. |
66 | | */ |
67 | | template <typename T> |
68 | | concept spanable_range = std::constructible_from<std::span<const std::ranges::range_value_t<T>>, T>; |
69 | | |
70 | | /** |
71 | | * Models a range that can be turned into a std::span<> with a static extent. |
72 | | * Typically, this is a std::array or a std::span derived from an array. |
73 | | */ |
74 | | // clang-format off |
75 | | template <typename T> |
76 | | concept statically_spanable_range = spanable_range<T> && |
77 | | decltype(std::span{std::declval<T&>()})::extent != std::dynamic_extent; |
78 | | |
79 | | // clang-format on |
80 | | |
81 | | /** |
82 | | * Find the length in bytes of a given contiguous range @p r. |
83 | | */ |
84 | 530M | inline constexpr size_t size_bytes(spanable_range auto&& r) { |
85 | 530M | return std::span{r}.size_bytes(); |
86 | 530M | } Unexecuted instantiation: _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__15arrayImLm4EEEEEmOT_ Unexecuted instantiation: _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIhLm32EEEEEmOT_ Unexecuted instantiation: _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIhLm2EEEEEmOT_ _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIhLm4EEEEEmOT_ Line | Count | Source | 84 | 652k | inline constexpr size_t size_bytes(spanable_range auto&& r) { | 85 | 652k | return std::span{r}.size_bytes(); | 86 | 652k | } |
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIhLm8EEEEEmOT_ Line | Count | Source | 84 | 24.8M | inline constexpr size_t size_bytes(spanable_range auto&& r) { | 85 | 24.8M | return std::span{r}.size_bytes(); | 86 | 24.8M | } |
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIjLm1EEEEEmOT_ Line | Count | Source | 84 | 357M | inline constexpr size_t size_bytes(spanable_range auto&& r) { | 85 | 357M | return std::span{r}.size_bytes(); | 86 | 357M | } |
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanImLm1EEEEEmOT_ Line | Count | Source | 84 | 135M | inline constexpr size_t size_bytes(spanable_range auto&& r) { | 85 | 135M | return std::span{r}.size_bytes(); | 86 | 135M | } |
Unexecuted instantiation: _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanItLm1EEEEEmOT_ _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIjLm18446744073709551615EEEEEmOT_ Line | Count | Source | 84 | 12.3M | inline constexpr size_t size_bytes(spanable_range auto&& r) { | 85 | 12.3M | return std::span{r}.size_bytes(); | 86 | 12.3M | } |
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEEEEmOT_ Line | Count | Source | 84 | 53.7k | inline constexpr size_t size_bytes(spanable_range auto&& r) { | 85 | 53.7k | return std::span{r}.size_bytes(); | 86 | 53.7k | } |
Unexecuted instantiation: _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanImLm18446744073709551615EEEEEmOT_ |
87 | | |
88 | | /** |
89 | | * Check that a given range @p r has a certain statically-known byte length. If |
90 | | * the range's extent is known at compile time, this is a static check, |
91 | | * otherwise a runtime argument check will be added. |
92 | | * |
93 | | * @throws Invalid_Argument if range @p r has a dynamic extent and does not |
94 | | * feature the expected byte length. |
95 | | */ |
96 | | template <size_t expected, spanable_range R> |
97 | 1.05G | inline constexpr void assert_exact_byte_length(R&& r) { |
98 | 1.05G | const std::span s{r}; |
99 | 1.05G | if constexpr(statically_spanable_range<R>) { |
100 | 1.05G | static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths"); |
101 | | } else { |
102 | | BOTAN_ASSERT(s.size_bytes() == expected, "memory region does not have expected byte lengths"); |
103 | | } |
104 | 1.05G | } Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm32ETkNS0_14spanable_rangeERNSt3__14spanIhLm32EEEEEvOT0_ Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm32ETkNS0_14spanable_rangeERNSt3__14spanIKhLm32EEEEEvOT0_ Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm32ETkNS0_14spanable_rangeERNSt3__15arrayImLm4EEEEEvOT0_ Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm2ETkNS0_14spanable_rangeERNSt3__14spanIhLm2EEEEEvOT0_ Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm2ETkNS0_14spanable_rangeERNSt3__14spanIKtLm1EEEEEvOT0_ _ZN5Botan6ranges24assert_exact_byte_lengthILm4ETkNS0_14spanable_rangeERNSt3__14spanIhLm4EEEEEvOT0_ Line | Count | Source | 97 | 1.30M | inline constexpr void assert_exact_byte_length(R&& r) { | 98 | 1.30M | const std::span s{r}; | 99 | 1.30M | if constexpr(statically_spanable_range<R>) { | 100 | 1.30M | static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 101 | | } else { | 102 | | BOTAN_ASSERT(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 103 | | } | 104 | 1.30M | } |
_ZN5Botan6ranges24assert_exact_byte_lengthILm4ETkNS0_14spanable_rangeERNSt3__14spanIKjLm1EEEEEvOT0_ Line | Count | Source | 97 | 652k | inline constexpr void assert_exact_byte_length(R&& r) { | 98 | 652k | const std::span s{r}; | 99 | 652k | if constexpr(statically_spanable_range<R>) { | 100 | 652k | static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 101 | | } else { | 102 | | BOTAN_ASSERT(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 103 | | } | 104 | 652k | } |
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeERNSt3__14spanIhLm8EEEEEvOT0_ Line | Count | Source | 97 | 46.0M | inline constexpr void assert_exact_byte_length(R&& r) { | 98 | 46.0M | const std::span s{r}; | 99 | 46.0M | if constexpr(statically_spanable_range<R>) { | 100 | 46.0M | static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 101 | | } else { | 102 | | BOTAN_ASSERT(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 103 | | } | 104 | 46.0M | } |
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeERNSt3__14spanIKmLm1EEEEEvOT0_ Line | Count | Source | 97 | 24.8M | inline constexpr void assert_exact_byte_length(R&& r) { | 98 | 24.8M | const std::span s{r}; | 99 | 24.8M | if constexpr(statically_spanable_range<R>) { | 100 | 24.8M | static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 101 | | } else { | 102 | | BOTAN_ASSERT(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 103 | | } | 104 | 24.8M | } |
_ZN5Botan6ranges24assert_exact_byte_lengthILm4ETkNS0_14spanable_rangeERNSt3__14spanIKhLm4EEEEEvOT0_ Line | Count | Source | 97 | 715M | inline constexpr void assert_exact_byte_length(R&& r) { | 98 | 715M | const std::span s{r}; | 99 | 715M | if constexpr(statically_spanable_range<R>) { | 100 | 715M | static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 101 | | } else { | 102 | | BOTAN_ASSERT(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 103 | | } | 104 | 715M | } |
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeERNSt3__14spanIKhLm8EEEEEvOT0_ Line | Count | Source | 97 | 270M | inline constexpr void assert_exact_byte_length(R&& r) { | 98 | 270M | const std::span s{r}; | 99 | 270M | if constexpr(statically_spanable_range<R>) { | 100 | 270M | static_assert(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 101 | | } else { | 102 | | BOTAN_ASSERT(s.size_bytes() == expected, "memory region does not have expected byte lengths"); | 103 | | } | 104 | 270M | } |
Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm16ETkNS0_14spanable_rangeERNSt3__14spanIKhLm16EEEEEvOT0_ Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm16ETkNS0_14spanable_rangeERNSt3__14spanIhLm16EEEEEvOT0_ Unexecuted instantiation: _ZN5Botan6ranges24assert_exact_byte_lengthILm2ETkNS0_14spanable_rangeERNSt3__14spanIKhLm2EEEEEvOT0_ |
105 | | |
106 | | /** |
107 | | * Check that a list of ranges (in @p r0 and @p rs) all have the same byte |
108 | | * lengths. If the first range's extent is known at compile time, this will be a |
109 | | * static check for all other ranges whose extents are known at compile time, |
110 | | * otherwise a runtime argument check will be added. |
111 | | * |
112 | | * @throws Invalid_Argument if any range has a dynamic extent and not all |
113 | | * ranges feature the same byte length. |
114 | | */ |
115 | | template <spanable_range R0, spanable_range... Rs> |
116 | | inline constexpr void assert_equal_byte_lengths(R0&& r0, Rs&&... rs) |
117 | | requires(sizeof...(Rs) > 0) |
118 | 545M | { |
119 | 545M | const std::span s0{r0}; |
120 | | |
121 | 545M | if constexpr(statically_spanable_range<R0>) { |
122 | 518M | constexpr size_t expected_size = s0.size_bytes(); |
123 | 518M | (assert_exact_byte_length<expected_size>(rs), ...); |
124 | 518M | } else { |
125 | 27.6M | const size_t expected_size = s0.size_bytes(); |
126 | 27.6M | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), |
127 | 27.6M | "memory regions don't have equal lengths"); |
128 | 27.6M | } |
129 | 545M | } Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm18446744073709551615EEEEEEvOT_DpOT0_QgtsZT0_Li0E Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__15arrayImLm4EEETpTkNS0_14spanable_rangeEJRNS2_4spanIhLm32EEEEEEvOT_DpOT0_QgtsZT0_Li0E Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__15arrayImLm4EEETpTkNS0_14spanable_rangeEJRNS2_4spanIKhLm32EEEEEEvOT_DpOT0_QgtsZT0_Li0E Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm32EEETpTkNS0_14spanable_rangeEJRNS2_5arrayImLm4EEEEEEvOT_DpOT0_QgtsZT0_Li0E Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm18446744073709551615EEES8_EEEvOT_DpOT0_QgtsZT0_Li0E Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm2EEETpTkNS0_14spanable_rangeEJRNS3_IKtLm1EEEEEEvOT_DpOT0_QgtsZT0_Li0E _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm4EEETpTkNS0_14spanable_rangeEJRNS3_IKjLm1EEEEEEvOT_DpOT0_QgtsZT0_Li0E Line | Count | Source | 118 | 652k | { | 119 | 652k | const std::span s0{r0}; | 120 | | | 121 | 652k | if constexpr(statically_spanable_range<R0>) { | 122 | 652k | constexpr size_t expected_size = s0.size_bytes(); | 123 | 652k | (assert_exact_byte_length<expected_size>(rs), ...); | 124 | | } else { | 125 | | const size_t expected_size = s0.size_bytes(); | 126 | | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), | 127 | | "memory regions don't have equal lengths"); | 128 | | } | 129 | 652k | } |
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm8EEETpTkNS0_14spanable_rangeEJRNS3_IKmLm1EEEEEEvOT_DpOT0_QgtsZT0_Li0E Line | Count | Source | 118 | 24.8M | { | 119 | 24.8M | const std::span s0{r0}; | 120 | | | 121 | 24.8M | if constexpr(statically_spanable_range<R0>) { | 122 | 24.8M | constexpr size_t expected_size = s0.size_bytes(); | 123 | 24.8M | (assert_exact_byte_length<expected_size>(rs), ...); | 124 | | } else { | 125 | | const size_t expected_size = s0.size_bytes(); | 126 | | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), | 127 | | "memory regions don't have equal lengths"); | 128 | | } | 129 | 24.8M | } |
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIjLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm18446744073709551615EEEEEEvOT_DpOT0_QgtsZT0_Li0E Line | Count | Source | 118 | 24.7M | { | 119 | 24.7M | const std::span s0{r0}; | 120 | | | 121 | | if constexpr(statically_spanable_range<R0>) { | 122 | | constexpr size_t expected_size = s0.size_bytes(); | 123 | | (assert_exact_byte_length<expected_size>(rs), ...); | 124 | 24.7M | } else { | 125 | 24.7M | const size_t expected_size = s0.size_bytes(); | 126 | 24.7M | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), | 127 | 24.7M | "memory regions don't have equal lengths"); | 128 | 24.7M | } | 129 | 24.7M | } |
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIjLm1EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm4EEEEEEvOT_DpOT0_QgtsZT0_Li0E Line | Count | Source | 118 | 357M | { | 119 | 357M | const std::span s0{r0}; | 120 | | | 121 | 357M | if constexpr(statically_spanable_range<R0>) { | 122 | 357M | constexpr size_t expected_size = s0.size_bytes(); | 123 | 357M | (assert_exact_byte_length<expected_size>(rs), ...); | 124 | | } else { | 125 | | const size_t expected_size = s0.size_bytes(); | 126 | | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), | 127 | | "memory regions don't have equal lengths"); | 128 | | } | 129 | 357M | } |
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKjLm18446744073709551615EEEEEEvOT_DpOT0_QgtsZT0_Li0E Line | Count | Source | 118 | 189k | { | 119 | 189k | const std::span s0{r0}; | 120 | | | 121 | | if constexpr(statically_spanable_range<R0>) { | 122 | | constexpr size_t expected_size = s0.size_bytes(); | 123 | | (assert_exact_byte_length<expected_size>(rs), ...); | 124 | 189k | } else { | 125 | 189k | const size_t expected_size = s0.size_bytes(); | 126 | 189k | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), | 127 | 189k | "memory regions don't have equal lengths"); | 128 | 189k | } | 129 | 189k | } |
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanImLm1EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm8EEEEEEvOT_DpOT0_QgtsZT0_Li0E Line | Count | Source | 118 | 135M | { | 119 | 135M | const std::span s0{r0}; | 120 | | | 121 | 135M | if constexpr(statically_spanable_range<R0>) { | 122 | 135M | constexpr size_t expected_size = s0.size_bytes(); | 123 | 135M | (assert_exact_byte_length<expected_size>(rs), ...); | 124 | | } else { | 125 | | const size_t expected_size = s0.size_bytes(); | 126 | | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), | 127 | | "memory regions don't have equal lengths"); | 128 | | } | 129 | 135M | } |
Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanItLm1EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm2EEEEEEvOT_DpOT0_QgtsZT0_Li0E _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKmLm18446744073709551615EEEEEEvOT_DpOT0_QgtsZT0_Li0E Line | Count | Source | 118 | 2.66M | { | 119 | 2.66M | const std::span s0{r0}; | 120 | | | 121 | | if constexpr(statically_spanable_range<R0>) { | 122 | | constexpr size_t expected_size = s0.size_bytes(); | 123 | | (assert_exact_byte_length<expected_size>(rs), ...); | 124 | 2.66M | } else { | 125 | 2.66M | const size_t expected_size = s0.size_bytes(); | 126 | 2.66M | BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...), | 127 | 2.66M | "memory regions don't have equal lengths"); | 128 | 2.66M | } | 129 | 2.66M | } |
Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRKNS2_6vectorIhNS_16secure_allocatorIhEEEEEEEvOT_DpOT0_QgtsZT0_Li0E Unexecuted instantiation: _ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanImLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm18446744073709551615EEEEEEvOT_DpOT0_QgtsZT0_Li0E |
130 | | |
131 | | } // namespace ranges |
132 | | |
133 | | namespace concepts { |
134 | | |
135 | | // TODO: C++20 provides concepts like std::ranges::range or ::sized_range |
136 | | // but at the time of this writing clang had not caught up on all |
137 | | // platforms. E.g. clang 14 on Xcode does not support ranges properly. |
138 | | |
139 | | template <typename IterT, typename ContainerT> |
140 | | concept container_iterator = |
141 | | std::same_as<IterT, typename ContainerT::iterator> || std::same_as<IterT, typename ContainerT::const_iterator>; |
142 | | |
143 | | template <typename PtrT, typename ContainerT> |
144 | | concept container_pointer = |
145 | | std::same_as<PtrT, typename ContainerT::pointer> || std::same_as<PtrT, typename ContainerT::const_pointer>; |
146 | | |
147 | | template <typename T> |
148 | | concept container = requires(T a) { |
149 | | { a.begin() } -> container_iterator<T>; |
150 | | { a.end() } -> container_iterator<T>; |
151 | | { a.cbegin() } -> container_iterator<T>; |
152 | | { a.cend() } -> container_iterator<T>; |
153 | | { a.size() } -> std::same_as<typename T::size_type>; |
154 | | typename T::value_type; |
155 | | }; |
156 | | |
157 | | template <typename T> |
158 | | concept contiguous_container = container<T> && requires(T a) { |
159 | | { a.data() } -> container_pointer<T>; |
160 | | }; |
161 | | |
162 | | template <typename T> |
163 | | concept has_empty = requires(T a) { |
164 | | { a.empty() } -> std::same_as<bool>; |
165 | | }; |
166 | | |
167 | | template <typename T> |
168 | | concept resizable_container = container<T> && requires(T& c, typename T::size_type s) { |
169 | | T(s); |
170 | | c.resize(s); |
171 | | }; |
172 | | |
173 | | template <typename T> |
174 | | concept resizable_byte_buffer = |
175 | | contiguous_container<T> && resizable_container<T> && std::same_as<typename T::value_type, uint8_t>; |
176 | | |
177 | | template <typename T> |
178 | | concept streamable = requires(std::ostream& os, T a) { os << a; }; |
179 | | |
180 | | template <class T> |
181 | | concept strong_type = is_strong_type_v<T>; |
182 | | |
183 | | template <class T> |
184 | | concept contiguous_strong_type = strong_type<T> && contiguous_container<T>; |
185 | | |
186 | | template <class T> |
187 | | concept unsigned_integral_strong_type = strong_type<T> && std::unsigned_integral<typename T::wrapped_type>; |
188 | | |
189 | | } // namespace concepts |
190 | | |
191 | | } // namespace Botan |
192 | | |
193 | | #endif |