Coverage Report

Created: 2025-07-18 06:20

/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
522M
inline constexpr size_t size_bytes(spanable_range auto&& r) {
85
522M
   return std::span{r}.size_bytes();
86
522M
}
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
729k
inline constexpr size_t size_bytes(spanable_range auto&& r) {
85
729k
   return std::span{r}.size_bytes();
86
729k
}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIhLm8EEEEEmOT_
Line
Count
Source
84
26.7M
inline constexpr size_t size_bytes(spanable_range auto&& r) {
85
26.7M
   return std::span{r}.size_bytes();
86
26.7M
}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIjLm1EEEEEmOT_
Line
Count
Source
84
339M
inline constexpr size_t size_bytes(spanable_range auto&& r) {
85
339M
   return std::span{r}.size_bytes();
86
339M
}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanImLm1EEEEEmOT_
Line
Count
Source
84
142M
inline constexpr size_t size_bytes(spanable_range auto&& r) {
85
142M
   return std::span{r}.size_bytes();
86
142M
}
Unexecuted instantiation: _ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanItLm1EEEEEmOT_
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIjLm18446744073709551615EEEEEmOT_
Line
Count
Source
84
13.1M
inline constexpr size_t size_bytes(spanable_range auto&& r) {
85
13.1M
   return std::span{r}.size_bytes();
86
13.1M
}
_ZN5Botan6ranges10size_bytesITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEEEEmOT_
Line
Count
Source
84
57.1k
inline constexpr size_t size_bytes(spanable_range auto&& r) {
85
57.1k
   return std::span{r}.size_bytes();
86
57.1k
}
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.04G
inline constexpr void assert_exact_byte_length(R&& r) {
98
1.04G
   const std::span s{r};
99
1.04G
   if constexpr(statically_spanable_range<R>) {
100
1.04G
      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.04G
}
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.45M
inline constexpr void assert_exact_byte_length(R&& r) {
98
1.45M
   const std::span s{r};
99
1.45M
   if constexpr(statically_spanable_range<R>) {
100
1.45M
      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.45M
}
_ZN5Botan6ranges24assert_exact_byte_lengthILm4ETkNS0_14spanable_rangeERNSt3__14spanIKjLm1EEEEEvOT0_
Line
Count
Source
97
729k
inline constexpr void assert_exact_byte_length(R&& r) {
98
729k
   const std::span s{r};
99
729k
   if constexpr(statically_spanable_range<R>) {
100
729k
      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
729k
}
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeERNSt3__14spanIhLm8EEEEEvOT0_
Line
Count
Source
97
49.6M
inline constexpr void assert_exact_byte_length(R&& r) {
98
49.6M
   const std::span s{r};
99
49.6M
   if constexpr(statically_spanable_range<R>) {
100
49.6M
      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
49.6M
}
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeERNSt3__14spanIKmLm1EEEEEvOT0_
Line
Count
Source
97
26.7M
inline constexpr void assert_exact_byte_length(R&& r) {
98
26.7M
   const std::span s{r};
99
26.7M
   if constexpr(statically_spanable_range<R>) {
100
26.7M
      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
26.7M
}
_ZN5Botan6ranges24assert_exact_byte_lengthILm4ETkNS0_14spanable_rangeERNSt3__14spanIKhLm4EEEEEvOT0_
Line
Count
Source
97
678M
inline constexpr void assert_exact_byte_length(R&& r) {
98
678M
   const std::span s{r};
99
678M
   if constexpr(statically_spanable_range<R>) {
100
678M
      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
678M
}
_ZN5Botan6ranges24assert_exact_byte_lengthILm8ETkNS0_14spanable_rangeERNSt3__14spanIKhLm8EEEEEvOT0_
Line
Count
Source
97
285M
inline constexpr void assert_exact_byte_length(R&& r) {
98
285M
   const std::span s{r};
99
285M
   if constexpr(statically_spanable_range<R>) {
100
285M
      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
285M
}
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
539M
{
119
539M
   const std::span s0{r0};
120
121
539M
   if constexpr(statically_spanable_range<R0>) {
122
509M
      constexpr size_t expected_size = s0.size_bytes();
123
509M
      (assert_exact_byte_length<expected_size>(rs), ...);
124
509M
   } else {
125
29.3M
      const size_t expected_size = s0.size_bytes();
126
29.3M
      BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...),
127
29.3M
                      "memory regions don't have equal lengths");
128
29.3M
   }
129
539M
}
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
729k
{
119
729k
   const std::span s0{r0};
120
121
729k
   if constexpr(statically_spanable_range<R0>) {
122
729k
      constexpr size_t expected_size = s0.size_bytes();
123
729k
      (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
729k
}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm8EEETpTkNS0_14spanable_rangeEJRNS3_IKmLm1EEEEEEvOT_DpOT0_QgtsZT0_Li0E
Line
Count
Source
118
26.7M
{
119
26.7M
   const std::span s0{r0};
120
121
26.7M
   if constexpr(statically_spanable_range<R0>) {
122
26.7M
      constexpr size_t expected_size = s0.size_bytes();
123
26.7M
      (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
26.7M
}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIjLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm18446744073709551615EEEEEEvOT_DpOT0_QgtsZT0_Li0E
Line
Count
Source
118
26.2M
{
119
26.2M
   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
26.2M
   } else {
125
26.2M
      const size_t expected_size = s0.size_bytes();
126
26.2M
      BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...),
127
26.2M
                      "memory regions don't have equal lengths");
128
26.2M
   }
129
26.2M
}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIjLm1EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm4EEEEEEvOT_DpOT0_QgtsZT0_Li0E
Line
Count
Source
118
339M
{
119
339M
   const std::span s0{r0};
120
121
339M
   if constexpr(statically_spanable_range<R0>) {
122
339M
      constexpr size_t expected_size = s0.size_bytes();
123
339M
      (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
339M
}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanIhLm18446744073709551615EEETpTkNS0_14spanable_rangeEJRNS3_IKjLm18446744073709551615EEEEEEvOT_DpOT0_QgtsZT0_Li0E
Line
Count
Source
118
206k
{
119
206k
   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
206k
   } else {
125
206k
      const size_t expected_size = s0.size_bytes();
126
206k
      BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...),
127
206k
                      "memory regions don't have equal lengths");
128
206k
   }
129
206k
}
_ZN5Botan6ranges25assert_equal_byte_lengthsITkNS0_14spanable_rangeERNSt3__14spanImLm1EEETpTkNS0_14spanable_rangeEJRNS3_IKhLm8EEEEEEvOT_DpOT0_QgtsZT0_Li0E
Line
Count
Source
118
142M
{
119
142M
   const std::span s0{r0};
120
121
142M
   if constexpr(statically_spanable_range<R0>) {
122
142M
      constexpr size_t expected_size = s0.size_bytes();
123
142M
      (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
142M
}
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.87M
{
119
2.87M
   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.87M
   } else {
125
2.87M
      const size_t expected_size = s0.size_bytes();
126
2.87M
      BOTAN_ARG_CHECK(((std::span<const std::ranges::range_value_t<Rs>>{rs}.size_bytes() == expected_size) && ...),
127
2.87M
                      "memory regions don't have equal lengths");
128
2.87M
   }
129
2.87M
}
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