Coverage Report

Created: 2025-06-11 06:40

/src/boringssl/include/openssl/span.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2017 The BoringSSL Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef OPENSSL_HEADER_SSL_SPAN_H
16
#define OPENSSL_HEADER_SSL_SPAN_H
17
18
#include <openssl/base.h>   // IWYU pragma: export
19
20
#if !defined(BORINGSSL_NO_CXX)
21
22
extern "C++" {
23
24
#include <stdlib.h>
25
26
#include <algorithm>
27
#include <string_view>
28
#include <type_traits>
29
30
#if __has_include(<version>)
31
#include <version>
32
#endif
33
34
#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L
35
#include <ranges>
36
BSSL_NAMESPACE_BEGIN
37
template <typename T>
38
class Span;
39
BSSL_NAMESPACE_END
40
41
// Mark `Span` as satisfying the `view` and `borrowed_range` concepts. This
42
// should be done before the definition of `Span`, so that any inlined calls to
43
// range functionality use the correct specializations.
44
template <typename T>
45
inline constexpr bool std::ranges::enable_view<bssl::Span<T>> = true;
46
template <typename T>
47
inline constexpr bool std::ranges::enable_borrowed_range<bssl::Span<T>> = true;
48
#endif
49
50
BSSL_NAMESPACE_BEGIN
51
52
template <typename T>
53
class Span;
54
55
namespace internal {
56
template <typename T>
57
class SpanBase {
58
  // Put comparison operator implementations into a base class with const T, so
59
  // they can be used with any type that implicitly converts into a Span.
60
  static_assert(std::is_const<T>::value,
61
                "Span<T> must be derived from SpanBase<const T>");
62
63
0
  friend bool operator==(Span<T> lhs, Span<T> rhs) {
64
0
    return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
65
0
  }
66
67
0
  friend bool operator!=(Span<T> lhs, Span<T> rhs) { return !(lhs == rhs); }
68
};
69
70
// Heuristically test whether C is a container type that can be converted into
71
// a Span<T> by checking for data() and size() member functions.
72
template <typename C, typename T>
73
using EnableIfContainer = std::enable_if_t<
74
    std::is_convertible_v<decltype(std::declval<C>().data()), T *> &&
75
    std::is_integral_v<decltype(std::declval<C>().size())>>;
76
77
}  // namespace internal
78
79
// A Span<T> is a non-owning reference to a contiguous array of objects of type
80
// |T|. Conceptually, a Span is a simple a pointer to |T| and a count of
81
// elements accessible via that pointer. The elements referenced by the Span can
82
// be mutated if |T| is mutable.
83
//
84
// A Span can be constructed from container types implementing |data()| and
85
// |size()| methods. If |T| is constant, construction from a container type is
86
// implicit. This allows writing methods that accept data from some unspecified
87
// container type:
88
//
89
// // Foo views data referenced by v.
90
// void Foo(bssl::Span<const uint8_t> v) { ... }
91
//
92
// std::vector<uint8_t> vec;
93
// Foo(vec);
94
//
95
// For mutable Spans, conversion is explicit:
96
//
97
// // FooMutate mutates data referenced by v.
98
// void FooMutate(bssl::Span<uint8_t> v) { ... }
99
//
100
// FooMutate(bssl::Span<uint8_t>(vec));
101
//
102
// You can also use C++17 class template argument deduction to construct Spans
103
// in order to deduce the type of the Span automatically.
104
//
105
// FooMutate(bssl::Span(vec));
106
//
107
// Note that Spans have value type sematics. They are cheap to construct and
108
// copy, and should be passed by value whenever a method would otherwise accept
109
// a reference or pointer to a container or array.
110
template <typename T>
111
class Span : private internal::SpanBase<const T> {
112
 public:
113
  static const size_t npos = static_cast<size_t>(-1);
114
115
  using element_type = T;
116
  using value_type = std::remove_cv_t<T>;
117
  using size_type = size_t;
118
  using difference_type = ptrdiff_t;
119
  using pointer = T *;
120
  using const_pointer = const T *;
121
  using reference = T &;
122
  using const_reference = const T &;
123
  using iterator = T *;
124
  using const_iterator = const T *;
125
126
0
  constexpr Span() : Span(nullptr, 0) {}
Unexecuted instantiation: bssl::Span<char const*>::Span()
Unexecuted instantiation: bssl::Span<unsigned char const>::Span()
Unexecuted instantiation: bssl::Span<unsigned short const>::Span()
Unexecuted instantiation: bssl::Span<char const>::Span()
Unexecuted instantiation: bssl::Span<unsigned char>::Span()
127
28.1k
  constexpr Span(T *ptr, size_t len) : data_(ptr), size_(len) {}
bssl::Span<unsigned char const>::Span(unsigned char const*, unsigned long)
Line
Count
Source
127
28.1k
  constexpr Span(T *ptr, size_t len) : data_(ptr), size_(len) {}
Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::Span(ssl_cipher_st const*, unsigned long)
Unexecuted instantiation: bssl::Span<bool const>::Span(bool const*, unsigned long)
Unexecuted instantiation: bssl::Span<char const*>::Span(char const**, unsigned long)
Unexecuted instantiation: bssl::Span<unsigned char>::Span(unsigned char*, unsigned long)
Unexecuted instantiation: bssl::Span<unsigned short const>::Span(unsigned short const*, unsigned long)
Unexecuted instantiation: bssl::Span<int const>::Span(int const*, unsigned long)
Unexecuted instantiation: bssl::Span<char const* const>::Span(char const* const*, unsigned long)
Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::Span(SignatureAlgorithmName const*, unsigned long)
Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::Span(bssl::VersionInfo const*, unsigned long)
Unexecuted instantiation: bssl::Span<char const>::Span(char const*, unsigned long)
Unexecuted instantiation: bssl::Span<unsigned short>::Span(unsigned short*, unsigned long)
Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::Span(bssl::NamedGroup const*, unsigned long)
128
129
  template <size_t N>
130
0
  constexpr Span(T (&array)[N]) : Span(array, N) {}
Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::Span<24ul>(ssl_cipher_st const (&) [24ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<32ul>(unsigned char const (&) [32ul])
Unexecuted instantiation: bssl::Span<char const* const>::Span<3ul>(char const* const (&) [3ul])
Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::Span<14ul>(SignatureAlgorithmName const (&) [14ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<4ul>(unsigned char const (&) [4ul])
Unexecuted instantiation: bssl::Span<unsigned short const>::Span<3ul>(unsigned short const (&) [3ul])
Unexecuted instantiation: bssl::Span<unsigned short const>::Span<4ul>(unsigned short const (&) [4ul])
Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::Span<7ul>(bssl::VersionInfo const (&) [7ul])
Unexecuted instantiation: bssl::Span<char const>::Span<34ul>(char const (&) [34ul])
Unexecuted instantiation: bssl::Span<char const>::Span<20ul>(char const (&) [20ul])
Unexecuted instantiation: bssl::Span<unsigned char>::Span<8ul>(unsigned char (&) [8ul])
Unexecuted instantiation: bssl::Span<unsigned char>::Span<80ul>(unsigned char (&) [80ul])
Unexecuted instantiation: bssl::Span<unsigned char>::Span<24ul>(unsigned char (&) [24ul])
Unexecuted instantiation: bssl::Span<unsigned char>::Span<32ul>(unsigned char (&) [32ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<1ul>(unsigned char const (&) [1ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<2ul>(unsigned char const (&) [2ul])
Unexecuted instantiation: bssl::Span<unsigned char>::Span<2ul>(unsigned char (&) [2ul])
Unexecuted instantiation: bssl::Span<unsigned short const>::Span<9ul>(unsigned short const (&) [9ul])
Unexecuted instantiation: bssl::Span<unsigned char>::Span<65ul>(unsigned char (&) [65ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<16ul>(unsigned char const (&) [16ul])
Unexecuted instantiation: bssl::Span<unsigned short const>::Span<2ul>(unsigned short const (&) [2ul])
Unexecuted instantiation: bssl::Span<unsigned short const>::Span<12ul>(unsigned short const (&) [12ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<8ul>(unsigned char const (&) [8ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<6ul>(unsigned char const (&) [6ul])
Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::Span<6ul>(bssl::NamedGroup const (&) [6ul])
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<65ul>(unsigned char const (&) [65ul])
131
132
  template <typename C, typename = internal::EnableIfContainer<C, T>,
133
            typename = std::enable_if_t<std::is_const<T>::value, C>>
134
  constexpr Span(const C &container)
135
2
      : data_(container.data()), size_(container.size()) {}
bssl::Span<bool const>::Span<bssl::Array<bool>, void, bssl::Array<bool> >(bssl::Array<bool> const&)
Line
Count
Source
135
2
      : data_(container.data()), size_(container.size()) {}
Unexecuted instantiation: bssl::Span<char const* const>::Span<bssl::Span<char const*>, void, bssl::Span<char const*> >(bssl::Span<char const*> const&)
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::InplaceVector<unsigned char, 48ul>, void, bssl::InplaceVector<unsigned char, 48ul> >(bssl::InplaceVector<unsigned char, 48ul> const&)
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::InplaceVector<unsigned char, 32ul>, void, bssl::InplaceVector<unsigned char, 32ul> >(bssl::InplaceVector<unsigned char, 32ul> const&)
Unexecuted instantiation: bssl::Span<unsigned short const>::Span<bssl::Array<unsigned short>, void, bssl::Array<unsigned short> >(bssl::Array<unsigned short> const&)
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::Array<unsigned char>, void, bssl::Array<unsigned char> >(bssl::Array<unsigned char> const&)
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::InplaceVector<unsigned char, 12ul>, void, bssl::InplaceVector<unsigned char, 12ul> >(bssl::InplaceVector<unsigned char, 12ul> const&)
Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::Span<unsigned char>, void, bssl::Span<unsigned char> >(bssl::Span<unsigned char> const&)
Unexecuted instantiation: bssl::Span<unsigned short const>::Span<bssl::Span<unsigned short>, void, bssl::Span<unsigned short> >(bssl::Span<unsigned short> const&)
136
137
  template <typename C, typename = internal::EnableIfContainer<C, T>,
138
            typename = std::enable_if_t<!std::is_const<T>::value, C>>
139
  constexpr explicit Span(C &container)
140
0
      : data_(container.data()), size_(container.size()) {}
Unexecuted instantiation: bssl::Span<unsigned char>::Span<bssl::Array<unsigned char>, void, bssl::Array<unsigned char> >(bssl::Array<unsigned char>&)
Unexecuted instantiation: bssl::Span<unsigned char>::Span<bssl::InplaceVector<unsigned char, 48ul>, void, bssl::InplaceVector<unsigned char, 48ul> >(bssl::InplaceVector<unsigned char, 48ul>&)
141
142
0
  constexpr T *data() const { return data_; }
Unexecuted instantiation: bssl::Span<unsigned char const>::data() const
Unexecuted instantiation: bssl::Span<char const*>::data() const
Unexecuted instantiation: bssl::Span<unsigned char>::data() const
Unexecuted instantiation: bssl::Span<unsigned short const>::data() const
Unexecuted instantiation: bssl::Span<char const>::data() const
Unexecuted instantiation: bssl::Span<unsigned short>::data() const
143
41.6k
  constexpr size_t size() const { return size_; }
bssl::Span<unsigned char const>::size() const
Line
Count
Source
143
41.6k
  constexpr size_t size() const { return size_; }
Unexecuted instantiation: bssl::Span<char const* const>::size() const
Unexecuted instantiation: bssl::Span<char const*>::size() const
bssl::Span<bool const>::size() const
Line
Count
Source
143
4
  constexpr size_t size() const { return size_; }
Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::size() const
Unexecuted instantiation: bssl::Span<unsigned char>::size() const
Unexecuted instantiation: bssl::Span<int const>::size() const
Unexecuted instantiation: bssl::Span<unsigned short const>::size() const
Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::size() const
Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::size() const
Unexecuted instantiation: bssl::Span<char const>::size() const
Unexecuted instantiation: bssl::Span<unsigned short>::size() const
Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::size() const
144
0
  constexpr bool empty() const { return size_ == 0; }
Unexecuted instantiation: bssl::Span<char const*>::empty() const
Unexecuted instantiation: bssl::Span<unsigned char>::empty() const
Unexecuted instantiation: bssl::Span<unsigned char const>::empty() const
Unexecuted instantiation: bssl::Span<unsigned short const>::empty() const
145
146
28.1k
  constexpr iterator begin() const { return data_; }
bssl::Span<unsigned char const>::begin() const
Line
Count
Source
146
28.1k
  constexpr iterator begin() const { return data_; }
bssl::Span<bool const>::begin() const
Line
Count
Source
146
2
  constexpr iterator begin() const { return data_; }
Unexecuted instantiation: bssl::Span<unsigned short const>::begin() const
147
  constexpr const_iterator cbegin() const { return data_; }
148
28.1k
  constexpr iterator end() const { return data_ + size_; }
bssl::Span<unsigned char const>::end() const
Line
Count
Source
148
28.1k
  constexpr iterator end() const { return data_ + size_; }
bssl::Span<bool const>::end() const
Line
Count
Source
148
2
  constexpr iterator end() const { return data_ + size_; }
Unexecuted instantiation: bssl::Span<unsigned short const>::end() const
149
  constexpr const_iterator cend() const { return end(); }
150
151
0
  constexpr T &front() const {
152
0
    if (size_ == 0) {
153
0
      abort();
154
0
    }
155
0
    return data_[0];
156
0
  }
157
0
  constexpr T &back() const {
158
0
    if (size_ == 0) {
159
0
      abort();
160
0
    }
161
0
    return data_[size_ - 1];
162
0
  }
Unexecuted instantiation: bssl::Span<unsigned char>::back() const
Unexecuted instantiation: bssl::Span<unsigned char const>::back() const
163
164
0
  constexpr T &operator[](size_t i) const {
165
0
    if (i >= size_) {
166
0
      abort();
167
0
    }
168
0
    return data_[i];
169
0
  }
Unexecuted instantiation: bssl::Span<char const*>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<char const* const>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<int const>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<unsigned char const>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<unsigned char>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<unsigned short const>::operator[](unsigned long) const
Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::operator[](unsigned long) const
170
  T &at(size_t i) const { return (*this)[i]; }
171
172
0
  constexpr Span subspan(size_t pos = 0, size_t len = npos) const {
173
0
    if (pos > size_) {
174
      // absl::Span throws an exception here. Note std::span and Chromium
175
      // base::span additionally forbid pos + len being out of range, with a
176
      // special case at npos/dynamic_extent, while absl::Span::subspan clips
177
      // the span. For now, we align with absl::Span in case we switch to it in
178
      // the future.
179
0
      abort();
180
0
    }
181
0
    return Span(data_ + pos, std::min(size_ - pos, len));
182
0
  }
Unexecuted instantiation: bssl::Span<char const*>::subspan(unsigned long, unsigned long) const
Unexecuted instantiation: bssl::Span<unsigned char>::subspan(unsigned long, unsigned long) const
Unexecuted instantiation: bssl::Span<unsigned char const>::subspan(unsigned long, unsigned long) const
183
184
0
  constexpr Span first(size_t len) const {
185
0
    if (len > size_) {
186
0
      abort();
187
0
    }
188
0
    return Span(data_, len);
189
0
  }
Unexecuted instantiation: bssl::Span<unsigned char>::first(unsigned long) const
Unexecuted instantiation: bssl::Span<unsigned char const>::first(unsigned long) const
190
191
0
  constexpr Span last(size_t len) const {
192
0
    if (len > size_) {
193
0
      abort();
194
0
    }
195
0
    return Span(data_ + size_ - len, len);
196
0
  }
Unexecuted instantiation: bssl::Span<unsigned char>::last(unsigned long) const
Unexecuted instantiation: bssl::Span<unsigned char const>::last(unsigned long) const
197
198
 private:
199
  T *data_;
200
  size_t size_;
201
};
202
203
template <typename T>
204
const size_t Span<T>::npos;
205
206
template <typename T>
207
Span(T *, size_t) -> Span<T>;
208
template <typename T, size_t size>
209
Span(T (&array)[size]) -> Span<T>;
210
template <
211
    typename C,
212
    typename T = std::remove_pointer_t<decltype(std::declval<C>().data())>,
213
    typename = internal::EnableIfContainer<C, T>>
214
Span(C &) -> Span<T>;
215
216
template <typename T>
217
constexpr Span<T> MakeSpan(T *ptr, size_t size) {
218
  return Span<T>(ptr, size);
219
}
220
221
template <typename C>
222
constexpr auto MakeSpan(C &c) -> decltype(MakeSpan(c.data(), c.size())) {
223
  return MakeSpan(c.data(), c.size());
224
}
225
226
template <typename T, size_t N>
227
constexpr Span<T> MakeSpan(T (&array)[N]) {
228
  return Span<T>(array, N);
229
}
230
231
template <typename T>
232
0
constexpr Span<const T> MakeConstSpan(T *ptr, size_t size) {
233
0
  return Span<const T>(ptr, size);
234
0
}
Unexecuted instantiation: bssl::Span<unsigned char const> bssl::MakeConstSpan<unsigned char const>(unsigned char const*, unsigned long)
Unexecuted instantiation: bssl::Span<unsigned char const> bssl::MakeConstSpan<unsigned char>(unsigned char*, unsigned long)
235
236
template <typename C>
237
constexpr auto MakeConstSpan(const C &c)
238
    -> decltype(MakeConstSpan(c.data(), c.size())) {
239
  return MakeConstSpan(c.data(), c.size());
240
}
241
242
template <typename T, size_t size>
243
constexpr Span<const T> MakeConstSpan(T (&array)[size]) {
244
  return array;
245
}
246
247
0
inline Span<const uint8_t> StringAsBytes(std::string_view s) {
248
0
  return MakeConstSpan(reinterpret_cast<const uint8_t *>(s.data()), s.size());
249
0
}
250
251
0
inline std::string_view BytesAsStringView(bssl::Span<const uint8_t> b) {
252
0
  return std::string_view(reinterpret_cast<const char *>(b.data()), b.size());
253
0
}
254
255
BSSL_NAMESPACE_END
256
257
}  // extern C++
258
259
#endif  // !defined(BORINGSSL_NO_CXX)
260
261
#endif  // OPENSSL_HEADER_SSL_SPAN_H