xref: /aosp_15_r20/external/cronet/base/containers/span.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_CONTAINERS_SPAN_H_
6 #define BASE_CONTAINERS_SPAN_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <algorithm>
12 #include <array>
13 #include <concepts>
14 #include <iterator>
15 #include <limits>
16 #include <memory>
17 #include <span>
18 #include <type_traits>
19 #include <utility>
20 
21 #include "base/check.h"
22 #include "base/compiler_specific.h"
23 #include "base/containers/checked_iterators.h"
24 #include "base/containers/dynamic_extent.h"
25 #include "base/numerics/safe_conversions.h"
26 #include "base/template_util.h"
27 #include "base/types/to_address.h"
28 #include "third_party/abseil-cpp/absl/base/attributes.h"
29 
30 namespace base {
31 
32 template <typename T,
33           size_t Extent = dynamic_extent,
34           typename InternalPtrType = T*>
35 class span;
36 
37 namespace internal {
38 
39 template <typename From, typename To>
40 concept LegalDataConversion =
41     std::convertible_to<std::remove_reference_t<From> (*)[],
42                         std::remove_reference_t<To> (*)[]>;
43 
44 template <typename T, typename It>
45 concept CompatibleIter = std::contiguous_iterator<It> &&
46                          LegalDataConversion<std::iter_reference_t<It>, T>;
47 
48 template <typename T, typename R>
49 concept CompatibleRange =
50     std::ranges::contiguous_range<R> && std::ranges::sized_range<R> &&
51     LegalDataConversion<std::ranges::range_reference_t<R>, T> &&
52     (std::ranges::borrowed_range<R> || std::is_const_v<T>);
53 
54 template <typename T>
55 concept LegacyRangeDataIsPointer = std::is_pointer_v<T>;
56 
57 template <typename R>
requires(R & r)58 concept LegacyRange = requires(R& r) {
59   { std::ranges::data(r) } -> LegacyRangeDataIsPointer;
60   { std::ranges::size(r) } -> std::convertible_to<size_t>;
61 };
62 
63 // NOTE: Ideally we'd just use `CompatibleRange`, however this currently breaks
64 // code that was written prior to C++20 being standardized and assumes providing
65 // .data() and .size() is sufficient.
66 // TODO: https://crbug.com/1504998 - Remove in favor of CompatibleRange and fix
67 // callsites.
68 template <typename T, typename R>
requires(R & r)69 concept LegacyCompatibleRange = LegacyRange<R> && requires(R& r) {
70   { *std::ranges::data(r) } -> LegalDataConversion<T>;
71 };
72 
73 template <size_t I>
74 using size_constant = std::integral_constant<size_t, I>;
75 
76 template <typename T>
77 struct ExtentImpl : size_constant<dynamic_extent> {};
78 
79 template <typename T, size_t N>
80 struct ExtentImpl<T[N]> : size_constant<N> {};
81 
82 template <typename T, size_t N>
83 struct ExtentImpl<std::array<T, N>> : size_constant<N> {};
84 
85 template <typename T, size_t N>
86 struct ExtentImpl<base::span<T, N>> : size_constant<N> {};
87 
88 template <typename T>
89 using Extent = ExtentImpl<std::remove_cvref_t<T>>;
90 
91 template <typename T>
92 inline constexpr size_t ExtentV = Extent<T>::value;
93 
94 // must_not_be_dynamic_extent prevents |dynamic_extent| from being returned in a
95 // constexpr context.
96 template <size_t kExtent>
97 constexpr size_t must_not_be_dynamic_extent() {
98   static_assert(
99       kExtent != dynamic_extent,
100       "EXTENT should only be used for containers with a static extent.");
101   return kExtent;
102 }
103 
104 template <class T, class U, size_t N, size_t M>
105   requires((N == M || N == dynamic_extent || M == dynamic_extent) &&
106            std::equality_comparable_with<T, U>)
107 constexpr bool span_cmp(span<T, N> l, span<U, M> r);
108 
109 }  // namespace internal
110 
111 // A span is a value type that represents an array of elements of type T. Since
112 // it only consists of a pointer to memory with an associated size, it is very
113 // light-weight. It is cheap to construct, copy, move and use spans, so that
114 // users are encouraged to use it as a pass-by-value parameter. A span does not
115 // own the underlying memory, so care must be taken to ensure that a span does
116 // not outlive the backing store.
117 //
118 // span is somewhat analogous to std::string_view, but with arbitrary element
119 // types, allowing mutation if T is non-const.
120 //
121 // span is implicitly convertible from C++ arrays, as well as most [1]
122 // container-like types that provide a data() and size() method (such as
123 // std::vector<T>). A mutable span<T> can also be implicitly converted to an
124 // immutable span<const T>.
125 //
126 // Consider using a span for functions that take a data pointer and size
127 // parameter: it allows the function to still act on an array-like type, while
128 // allowing the caller code to be a bit more concise.
129 //
130 // For read-only data access pass a span<const T>: the caller can supply either
131 // a span<const T> or a span<T>, while the callee will have a read-only view.
132 // For read-write access a mutable span<T> is required.
133 //
134 // Without span:
135 //   Read-Only:
136 //     // std::string HexEncode(const uint8_t* data, size_t size);
137 //     std::vector<uint8_t> data_buffer = GenerateData();
138 //     std::string r = HexEncode(data_buffer.data(), data_buffer.size());
139 //
140 //  Mutable:
141 //     // ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args...);
142 //     char str_buffer[100];
143 //     SafeSNPrintf(str_buffer, sizeof(str_buffer), "Pi ~= %lf", 3.14);
144 //
145 // With span:
146 //   Read-Only:
147 //     // std::string HexEncode(base::span<const uint8_t> data);
148 //     std::vector<uint8_t> data_buffer = GenerateData();
149 //     std::string r = HexEncode(data_buffer);
150 //
151 //  Mutable:
152 //     // ssize_t SafeSNPrintf(base::span<char>, const char* fmt, Args...);
153 //     char str_buffer[100];
154 //     SafeSNPrintf(str_buffer, "Pi ~= %lf", 3.14);
155 //
156 // Dynamic vs Fixed size spans
157 // ---------------------------
158 //
159 // Normally spans have a dynamic size, which is represented as a type as
160 // `span<T>`. However it is possible to encode the size of the span into the
161 // type as a second parameter such as `span<T, N>`. When working with fixed-size
162 // spans, the compiler will check the size of operations and prevent compilation
163 // when an invalid size is used for an operation such as assignment or
164 // `copy_from()`. However operations that produce a new span will make a
165 // dynamic-sized span by default. See below for how to prevent that.
166 //
167 // Fixed-size spans implicitly convert to a dynamic-size span, throwing away the
168 // compile-time size information from the type signature. So most code should
169 // work with dynamic-sized `span<T>` types and not worry about the existence of
170 // fixed-size spans.
171 //
172 // It is possible to convert from a dynamic-size to a fixed-size span (or to
173 // move from a fixed-size span to another fixed-size span) but it requires
174 // writing an the size explicitly in the code. Methods like `first` can be
175 // passed a size as a template argument, such as `first<N>()` to generate a
176 // fixed-size span. And the `make_span` function can be given a compile-time
177 // size in a similar way with `make_span<N>()`.
178 //
179 // Spans with "const" and pointers
180 // -------------------------------
181 //
182 // Const and pointers can get confusing. Here are vectors of pointers and their
183 // corresponding spans:
184 //
185 //   const std::vector<int*>        =>  base::span<int* const>
186 //   std::vector<const int*>        =>  base::span<const int*>
187 //   const std::vector<const int*>  =>  base::span<const int* const>
188 //
189 // Differences from the C++ standard
190 // ---------------------------------
191 //
192 // http://eel.is/c++draft/views.span contains the latest C++ draft of std::span.
193 // Chromium tries to follow the draft as close as possible. Differences between
194 // the draft and the implementation are documented in subsections below.
195 //
196 // Differences from [span.overview]:
197 // - Dynamic spans are implemented as a partial specialization of the regular
198 //   class template. This leads to significantly simpler checks involving the
199 //   extent, at the expense of some duplicated code. The same strategy is used
200 //   by libc++.
201 //
202 // Differences from [span.objectrep]:
203 // - as_bytes() and as_writable_bytes() return spans of uint8_t instead of
204 //   std::byte.
205 //
206 // Differences from [span.cons]:
207 // - The constructors from a contiguous range apart from a C array are folded
208 //   into a single one, using a construct similarly to the one proposed
209 //   (but not standardized) in https://wg21.link/P1419.
210 //   The C array constructor is kept so that a span can be constructed from
211 //   an init list like {{1, 2, 3}}.
212 //   TODO: https://crbug.com/828324 - Consider adding C++26's constructor from
213 //   a std::initializer_list instead.
214 // - The conversion constructors from a contiguous range into a dynamic span
215 //   don't check for the range concept, but rather whether std::ranges::data
216 //   and std::ranges::size are well formed. This is due to legacy reasons and
217 //   should be fixed.
218 //
219 // Differences from [span.deduct]:
220 // - The deduction guides from a contiguous range are folded into a single one,
221 //   and treat borrowed ranges correctly.
222 // - Add deduction guide from rvalue array.
223 //
224 // Other differences:
225 // - Using StrictNumeric<size_t> instead of size_t where possible.
226 //
227 // Additions beyond the C++ standard draft
228 // - as_chars() function.
229 // - as_writable_chars() function.
230 // - as_byte_span() function.
231 // - as_writable_byte_span() function.
232 // - copy_from() method.
233 // - span_from_ref() function.
234 // - byte_span_from_ref() function.
235 // - span_from_cstring() function.
236 // - byte_span_from_cstring() function.
237 // - split_at() method.
238 // - operator==() comparator function.
239 //
240 // Furthermore, all constructors and methods are marked noexcept due to the lack
241 // of exceptions in Chromium.
242 //
243 // Due to the lack of class template argument deduction guides in C++14
244 // appropriate make_span() utility functions are provided for historic reasons.
245 
246 // [span], class template span
247 template <typename T, size_t N, typename InternalPtrType>
248 class GSL_POINTER span {
249  public:
250   using element_type = T;
251   using value_type = std::remove_cv_t<T>;
252   using size_type = size_t;
253   using difference_type = ptrdiff_t;
254   using pointer = T*;
255   using const_pointer = const T*;
256   using reference = T&;
257   using const_reference = const T&;
258   using iterator = CheckedContiguousIterator<T>;
259   using reverse_iterator = std::reverse_iterator<iterator>;
260   static constexpr size_t extent = N;
261 
262   // [span.cons], span constructors, copy, assignment, and destructor
263   constexpr span() noexcept
264     requires(N == 0)
265   = default;
266 
267   // Constructs a span from a contiguous iterator and a size.
268   //
269   // # Checks
270   // The function CHECKs that `count` matches the template parameter `N` and
271   // will terminate otherwise.
272   //
273   // # Safety
274   // The iterator must point to the first of at least `count` many elements, or
275   // Undefined Behaviour can result as the span will allow access beyond the
276   // valid range of the collection pointed to by the iterator.
277   template <typename It>
278     requires(internal::CompatibleIter<T, It>)
279   UNSAFE_BUFFER_USAGE explicit constexpr span(
280       It first,
281       StrictNumeric<size_t> count) noexcept
282       :  // The use of to_address() here is to handle the case where the
283          // iterator `first` is pointing to the container's `end()`. In that
284          // case we can not use the address returned from the iterator, or
285          // dereference it through the iterator's `operator*`, but we can store
286          // it. We must assume in this case that `count` is 0, since the
287          // iterator does not point to valid data. Future hardening of iterators
288          // may disallow pulling the address from `end()`, as demonstrated by
289          // asserts() in libstdc++:
290          // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93960.
291          //
292          // The span API dictates that the `data()` is accessible when size is
293          // 0, since the pointer may be valid, so we cannot prevent storing and
294          // giving out an invalid pointer here without breaking API
295          // compatibility and our unit tests. Thus protecting against this can
296          // likely only be successful from inside iterators themselves, where
297          // the context about the pointer is known.
298          //
299          // We can not protect here generally against an invalid iterator/count
300          // being passed in, since we have no context to determine if the
301          // iterator or count are valid.
302         data_(base::to_address(first)) {
303     // Guarantees that the N in the type signature is correct.
304     CHECK(N == count);
305   }
306 
307   // Constructs a span from a contiguous iterator and a size.
308   //
309   // # Checks
310   // The function CHECKs that `it <= end` and will terminate otherwise.
311   //
312   // # Safety
313   // The begin and end iterators must be for the same allocation or Undefined
314   // Behaviour can result as the span will allow access beyond the valid range
315   // of the collection pointed to by `begin`.
316   template <typename It, typename End>
317     requires(internal::CompatibleIter<T, It> &&
318              std::sized_sentinel_for<End, It> &&
319              !std::convertible_to<End, size_t>)
320   UNSAFE_BUFFER_USAGE explicit constexpr span(It begin, End end) noexcept
321       // SAFETY: The caller must guarantee that the iterator and end sentinel
322       // are part of the same allocation, in which case it is the number of
323       // elements between the iterators and thus a valid size for the pointer to
324       // the element at `begin`.
325       //
326       // We CHECK that `end - begin` did not underflow below. Normally checking
327       // correctness afterward is flawed, however underflow is not UB and the
328       // size is not converted to an invalid pointer (which would be UB) before
329       // we CHECK for underflow.
330       : UNSAFE_BUFFERS(span(begin, static_cast<size_t>(end - begin))) {
331     // Verify `end - begin` did not underflow.
332     CHECK(begin <= end);
333   }
334 
335   // NOLINTNEXTLINE(google-explicit-constructor)
336   constexpr span(T (&arr)[N]) noexcept
337       // SAFETY: The std::ranges::size() function gives the number of elements
338       // pointed to by the std::ranges::data() function, which meets the
339       // requirement of span.
340       : UNSAFE_BUFFERS(span(std::ranges::data(arr), std::ranges::size(arr))) {}
341 
342   template <typename R, size_t X = internal::ExtentV<R>>
343     requires(internal::CompatibleRange<T, R> && (X == N || X == dynamic_extent))
344   // NOLINTNEXTLINE(google-explicit-constructor)
345   explicit(X == dynamic_extent) constexpr span(R&& range) noexcept
346       // SAFETY: The std::ranges::size() function gives the number of elements
347       // pointed to by the std::ranges::data() function, which meets the
348       // requirement of span.
349       : UNSAFE_BUFFERS(
350             span(std::ranges::data(range), std::ranges::size(range))) {}
351 
352   // [span.sub], span subviews
353   template <size_t Count>
354   constexpr span<T, Count> first() const noexcept
355     requires(Count <= N)
356   {
357     // SAFETY: span provides that data() points to at least `N` many elements.
358     // `Count` is non-negative by its type and `Count <= N` from the requires
359     // condition. So `Count` is a valid new size for `data()`.
360     return UNSAFE_BUFFERS(span<T, Count>(data(), Count));
361   }
362 
363   template <size_t Count>
364   constexpr span<T, Count> last() const noexcept
365     requires(Count <= N)
366   {
367     // SAFETY: span provides that data() points to at least `N` many elements.
368     // `Count` is non-negative by its type and `Count <= N` from the requires
369     // condition. So `0 <= N - Count <= N`, meaning `N - Count` is a valid new
370     // size for `data()` and it will point to `Count` many elements.`
371     return UNSAFE_BUFFERS(span<T, Count>(data() + (N - Count), Count));
372   }
373 
374   // Returns a span over the first `count` elements.
375   //
376   // # Checks
377   // The function CHECKs that the span contains at least `count` elements and
378   // will terminate otherwise.
379   constexpr span<T> first(StrictNumeric<size_t> count) const noexcept {
380     CHECK_LE(size_t{count}, size());
381     // SAFETY: span provides that data() points to at least `N` many elements.
382     // `count` is non-negative by its type and `count <= N` from the CHECK
383     // above. So `count` is a valid new size for `data()`.
384     return UNSAFE_BUFFERS({data(), count});
385   }
386 
387   // Returns a span over the last `count` elements.
388   //
389   // # Checks
390   // The function CHECKs that the span contains at least `count` elements and
391   // will terminate otherwise.
392   constexpr span<T> last(StrictNumeric<size_t> count) const noexcept {
393     CHECK_LE(size_t{count}, N);
394     // SAFETY: span provides that data() points to at least `N` many elements.
395     // `count` is non-negative by its type and `count <= N` from the CHECK
396     // above. So `0 <= N - count <= N`, meaning `N - count` is a valid new size
397     // for `data()` and it will point to `count` many elements.
398     return UNSAFE_BUFFERS({data() + (N - size_t{count}), count});
399   }
400 
401   template <size_t Offset, size_t Count = dynamic_extent>
402   constexpr auto subspan() const noexcept
403     requires(Offset <= N && (Count == dynamic_extent || Count <= N - Offset))
404   {
405     constexpr size_t kExtent = Count != dynamic_extent ? Count : N - Offset;
406     // SAFETY: span provides that data() points to at least `N` many elements.
407     //
408     // If Count is dynamic_extent, kExtent becomes `N - Offset`. Since `Offset
409     // <= N` from the requires condition, then `Offset` is a valid offset for
410     // data(), and `Offset + kExtent = Offset + N - Offset = N >= Offset` is
411     // also a valid offset that is not before `Offset`. This makes a span at
412     // `Offset` with size `kExtent` valid.
413     //
414     // Otherwise `Count <= N - Offset` and `0 <= Offset <= N` by the requires
415     // condition, so `Offset <= N - Count` and `N - Count` can not underflow.
416     // Then `Offset` is a valid offset for data() and `kExtent` is `Count <= N -
417     // Offset`, so `Offset + kExtent <= Offset + N - Offset = N` which makes
418     // both `Offset` and `Offset + kExtent` valid offsets for data(), and since
419     // `kExtent` is non-negative, `Offset + kExtent` is not before `Offset` so
420     // `kExtent` is a valid size for the span at `data() + Offset`.
421     return UNSAFE_BUFFERS(span<T, kExtent>(data() + Offset, kExtent));
422   }
423 
424   // Returns a span over the first `count` elements starting at the given
425   // `offset` from the start of the span.
426   //
427   // # Checks
428   // The function CHECKs that the span contains at least `offset + count`
429   // elements, or at least `offset` elements if `count` is not specified, and
430   // will terminate otherwise.
431   constexpr span<T> subspan(size_t offset,
432                             size_t count = dynamic_extent) const noexcept {
433     CHECK_LE(offset, N);
434     CHECK(count == dynamic_extent || count <= N - offset);
435     const size_t new_extent = count != dynamic_extent ? count : N - offset;
436     // SAFETY: span provides that data() points to at least `N` many elements.
437     //
438     // If Count is dynamic_extent, `new_extent` becomes `N - offset`. Since
439     // `offset <= N` from the requires condition, then `offset` is a valid
440     // offset for data(), and `offset + new_extent = offset + N - offset = N >=
441     // offset` is also a valid offset that is not before `offset`. This makes a
442     // span at `offset` with size `new_extent` valid.
443     //
444     // Otherwise `count <= N - offset` and `0 <= offset <= N` by the requires
445     // condition, so `offset <= N - count` and `N - count` can not underflow.
446     // Then `offset` is a valid offset for data() and `new_extent` is `count <=
447     // N - offset`, so `offset + new_extent <= offset + N - offset = N` which
448     // makes both `offset` and `offset + new_extent` valid offsets for data(),
449     // and since `new_extent` is non-negative, `offset + new_extent` is not
450     // before `offset` so `new_extent` is a valid size for the span at `data() +
451     // offset`.
452     return UNSAFE_BUFFERS({data() + offset, new_extent});
453   }
454 
455   // Splits a span into two at the given `offset`, returning two spans that
456   // cover the full range of the original span.
457   //
458   // Similar to calling subspan() with the `offset` as the length on the first
459   // call, and then the `offset` as the offset in the second.
460   //
461   // The split_at<N>() overload allows construction of a fixed-size span from a
462   // compile-time constant. If the input span is fixed-size, both output output
463   // spans will be. Otherwise, the first will be fixed-size and the second will
464   // be dynamic-size.
465   //
466   // This is a non-std extension that  is inspired by the Rust slice::split_at()
467   // and split_at_mut() methods.
468   //
469   // # Checks
470   // The function CHECKs that the span contains at least `offset` elements and
471   // will terminate otherwise.
472   constexpr std::pair<span<T>, span<T>> split_at(size_t offset) const noexcept {
473     return {first(offset), subspan(offset)};
474   }
475 
476   template <size_t Offset>
477     requires(Offset <= N)
478   constexpr std::pair<span<T, Offset>, span<T, N - Offset>> split_at()
479       const noexcept {
480     return {first<Offset>(), subspan<Offset, N - Offset>()};
481   }
482 
483   // [span.obs], span observers
484   constexpr size_t size() const noexcept { return N; }
485   constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); }
486   [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
487 
488   // [span.elem], span element access
489   //
490   // # Checks
491   // The function CHECKs that the `idx` is inside the span and will terminate
492   // otherwise.
493   constexpr T& operator[](size_t idx) const noexcept {
494     CHECK_LT(idx, size());
495     // SAFETY: Since data() always points to at least `N` elements, the check
496     // above ensures `idx < N` and is thus in range for data().
497     return UNSAFE_BUFFERS(data()[idx]);
498   }
499 
500   constexpr T& front() const noexcept
501     requires(N > 0)
502   {
503     // SAFETY: Since data() always points to at least `N` elements, the requires
504     // constraint above ensures `0 < N` and is thus in range for data().
505     return UNSAFE_BUFFERS(data()[0]);
506   }
507 
508   constexpr T& back() const noexcept
509     requires(N > 0)
510   {
511     // SAFETY: Since data() always points to at least `N` elements, the requires
512     // constraint above ensures `N > 0` and thus `N - 1` does not underflow and
513     // is in range for data().
514     return UNSAFE_BUFFERS(data()[N - 1]);
515   }
516 
517   // Returns a pointer to the first element in the span. If the span is empty
518   // (`size()` is 0), the returned pointer may or may not be null, and it must
519   // not be dereferenced.
520   //
521   // It is always valid to add `size()` to the the pointer in C++ code, though
522   // it may be invalid in C code when the span is empty.
523   constexpr T* data() const noexcept { return data_; }
524 
525   // [span.iter], span iterator support
526   constexpr iterator begin() const noexcept {
527     // SAFETY: span provides that data() points to at least `size()` many
528     // elements, and size() is non-negative. So data() + size() is a valid
529     // pointer for the data() allocation.
530     return UNSAFE_BUFFERS(iterator(data(), data() + size()));
531   }
532 
533   constexpr iterator end() const noexcept {
534     // SAFETY: span provides that data() points to at least `size()` many
535     // elements, and size() is non-negative. So data() + size() is a valid
536     // pointer for the data() allocation.
537     return UNSAFE_BUFFERS(iterator(data(), data() + size(), data() + size()));
538   }
539 
540   constexpr reverse_iterator rbegin() const noexcept {
541     return reverse_iterator(end());
542   }
543 
544   constexpr reverse_iterator rend() const noexcept {
545     return reverse_iterator(begin());
546   }
547 
548   // Bounds-checked copy from a non-overlapping span. The spans must be the
549   // exact same size or a hard CHECK() occurs. If the two spans overlap,
550   // Undefined Behaviour occurs.
551   //
552   // This is a non-std extension that is inspired by the Rust
553   // slice::copy_from_slice() method.
554   //
555   // # Checks
556   // The function CHECKs that the `other` span has the same size as itself and
557   // will terminate otherwise.
558   constexpr void copy_from(span<const T, N> other)
559     requires(!std::is_const_v<T>)
560   {
561     CHECK_EQ(size_bytes(), other.size_bytes());
562     // Verify non-overlapping in developer builds.
563     //
564     // SAFETY: span provides that data() points to at least size() many
565     // elements, so adding size() to the data() pointer is well-defined.
566     DCHECK(UNSAFE_BUFFERS(data() + size()) <= other.data() ||
567            data() >= UNSAFE_BUFFERS(other.data() + other.size()));
568     // When compiling with -Oz, std::ranges::copy() does not get inlined, which
569     // makes copy_from() very expensive compared to memcpy for small sizes (up
570     // to around 4x slower). We observe that this is because ranges::copy() uses
571     // begin()/end() and span's iterators are checked iterators, not just
572     // pointers. This additional complexity prevents inlining and breaks the
573     // ability for the compiler to eliminate code.
574     //
575     // See also https://crbug.com/1396134.
576     //
577     // We also see std::copy() (with pointer arguments! not iterators) optimize
578     // and inline better than memcpy() since memcpy() needs to rely on
579     // size_bytes(), which while computable at compile time when `other` has a
580     // fixed size, the optimizer stumbles on with -Oz.
581     //
582     // SAFETY: The copy() here does not check bounds, but we have verified that
583     // `this` and `other` have the same bounds above (and are pointers of the
584     // same type), so `data()` and `other.data()` both have at least
585     // `other.size()` elements.
586     UNSAFE_BUFFERS(
587         std::copy(other.data(), other.data() + other.size(), data()));
588   }
589 
590   // Implicit conversion from std::span<T, N> to base::span<T, N>.
591   //
592   // We get other conversions for free from std::span's constructors, but it
593   // does not deduce N on its range constructor.
594   span(std::span<std::remove_const_t<T>, N> other)
595       :  // SAFETY: std::span contains a valid data pointer and size such
596          // that pointer+size remains valid.
597         UNSAFE_BUFFERS(
598             span(std::ranges::data(other), std::ranges::size(other))) {}
599   span(std::span<T, N> other)
600     requires(std::is_const_v<T>)
601       :  // SAFETY: std::span contains a valid data pointer and size such
602          // that pointer+size remains valid.
603         UNSAFE_BUFFERS(
604             span(std::ranges::data(other), std::ranges::size(other))) {}
605 
606   // Implicit conversion from base::span<T, N> to std::span<T, N>.
607   //
608   // We get other conversions for free from std::span's constructors, but it
609   // does not deduce N on its range constructor.
610   operator std::span<T, N>() const { return std::span<T, N>(*this); }
611   operator std::span<const T, N>() const
612     requires(!std::is_const_v<T>)
613   {
614     return std::span<const T, N>(*this);
615   }
616 
617   // Compares two spans for equality by comparing the objects pointed to by the
618   // spans. The operation is defined for spans of different types as long as the
619   // types are themselves comparable.
620   //
621   // For primitive types, this replaces the less safe `memcmp` function, where
622   // `memcmp(a.data(), b.data(), a.size())` can be written as `a == b` and can
623   // no longer go outside the bounds of `b`. Otherwise, it replaced std::equal
624   // or std::ranges::equal when working with spans, and when no projection is
625   // needed.
626   //
627   // If the spans are of different sizes, they are not equal. If both spans are
628   // empty, they are always equal (even though their data pointers may differ).
629   //
630   // # Implementation note
631   // The non-template overloads allow implicit conversions to span for
632   // comparison.
633   friend constexpr bool operator==(span lhs, span rhs)
634     requires(std::equality_comparable<const T>)
635   {
636     return internal::span_cmp(span<const T, N>(lhs), span<const T, N>(rhs));
637   }
638   friend constexpr bool operator==(span lhs, span<const T, N> rhs)
639     requires(!std::is_const_v<T> && std::equality_comparable<const T>)
640   {
641     return internal::span_cmp(span<const T, N>(lhs), span<const T, N>(rhs));
642   }
643   template <class U, size_t M>
644     requires((N == M || M == dynamic_extent) &&
645              std::equality_comparable_with<const T, const U>)
646   friend constexpr bool operator==(span lhs, span<U, M> rhs) {
647     return internal::span_cmp(span<const T, N>(lhs), span<const U, M>(rhs));
648   }
649 
650  private:
651   // This field is not a raw_ptr<> since span is mostly used for stack
652   // variables. Use `raw_span` instead for class fields, which does use
653   // raw_ptr<> internally.
654   InternalPtrType data_ = nullptr;
655 };
656 
657 // [span], class template span
658 template <typename T, typename InternalPtrType>
659 class GSL_POINTER span<T, dynamic_extent, InternalPtrType> {
660  public:
661   using element_type = T;
662   using value_type = std::remove_cv_t<T>;
663   using size_type = size_t;
664   using difference_type = ptrdiff_t;
665   using pointer = T*;
666   using const_pointer = const T*;
667   using reference = T&;
668   using const_reference = const T&;
669   using iterator = CheckedContiguousIterator<T>;
670   using reverse_iterator = std::reverse_iterator<iterator>;
671   static constexpr size_t extent = dynamic_extent;
672 
673   constexpr span() noexcept = default;
674 
675   // Constructs a span from a contiguous iterator and a size.
676   //
677   // # Safety
678   // The iterator must point to the first of at least `count` many elements, or
679   // Undefined Behaviour can result as the span will allow access beyond the
680   // valid range of the collection pointed to by the iterator.
681   template <typename It>
682     requires(internal::CompatibleIter<T, It>)
683   UNSAFE_BUFFER_USAGE constexpr span(It first,
684                                      StrictNumeric<size_t> count) noexcept
685       // The use of to_address() here is to handle the case where the iterator
686       // `first` is pointing to the container's `end()`. In that case we can
687       // not use the address returned from the iterator, or dereference it
688       // through the iterator's `operator*`, but we can store it. We must
689       // assume in this case that `count` is 0, since the iterator does not
690       // point to valid data. Future hardening of iterators may disallow
691       // pulling the address from `end()`, as demonstrated by asserts() in
692       // libstdc++: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93960.
693       //
694       // The span API dictates that the `data()` is accessible when size is 0,
695       // since the pointer may be valid, so we cannot prevent storing and
696       // giving out an invalid pointer here without breaking API compatibility
697       // and our unit tests. Thus protecting against this can likely only be
698       // successful from inside iterators themselves, where the context about
699       // the pointer is known.
700       //
701       // We can not protect here generally against an invalid iterator/count
702       // being passed in, since we have no context to determine if the
703       // iterator or count are valid.
704       : data_(base::to_address(first)), size_(count) {}
705 
706   // Constructs a span from a contiguous iterator and a size.
707   //
708   // # Safety
709   // The begin and end iterators must be for the same allocation, and `begin <=
710   // end` or Undefined Behaviour can result as the span will allow access beyond
711   // the valid range of the collection pointed to by `begin`.
712   template <typename It, typename End>
713     requires(internal::CompatibleIter<T, It> &&
714              std::sized_sentinel_for<End, It> &&
715              !std::convertible_to<End, size_t>)
716   UNSAFE_BUFFER_USAGE constexpr span(It begin, End end) noexcept
717       // SAFETY: The caller must guarantee that the iterator and end sentinel
718       // are part of the same allocation, in which case it is the number of
719       // elements between the iterators and thus a valid size for the pointer to
720       // the element at `begin`.
721       //
722       // We CHECK that `end - begin` did not underflow below. Normally checking
723       // correctness afterward is flawed, however underflow is not UB and the
724       // size is not converted to an invalid pointer (which would be UB) before
725       // we CHECK for underflow.
726       : UNSAFE_BUFFERS(span(begin, static_cast<size_t>(end - begin))) {
727     // Verify `end - begin` did not underflow.
728     CHECK(begin <= end);
729   }
730 
731   template <size_t N>
732   // NOLINTNEXTLINE(google-explicit-constructor)
733   constexpr span(T (&arr)[N]) noexcept
734       // SAFETY: The std::ranges::size() function gives the number of elements
735       // pointed to by the std::ranges::data() function, which meets the
736       // requirement of span.
737       : UNSAFE_BUFFERS(span(std::ranges::data(arr), std::ranges::size(arr))) {}
738 
739   template <typename R>
740     requires(internal::LegacyCompatibleRange<T, R>)
741   // NOLINTNEXTLINE(google-explicit-constructor)
742   constexpr span(R&& range) noexcept
743       // SAFETY: The std::ranges::size() function gives the number of elements
744       // pointed to by the std::ranges::data() function, which meets the
745       // requirement of span.
746       : UNSAFE_BUFFERS(
747             span(std::ranges::data(range), std::ranges::size(range))) {}
748 
749   // [span.sub], span subviews
750   template <size_t Count>
751   constexpr span<T, Count> first() const noexcept {
752     CHECK_LE(Count, size());
753     // SAFETY: span provides that data() points to at least `size()` many
754     // elements. `Count` is non-negative by its type and `Count <= size()` from
755     // the CHECK above. So `Count` is a valid new size for `data()`.
756     return UNSAFE_BUFFERS(span<T, Count>(data(), Count));
757   }
758 
759   template <size_t Count>
760   constexpr span<T, Count> last() const noexcept {
761     CHECK_LE(Count, size());
762     // SAFETY: span provides that data() points to at least `size()` many
763     // elements. `Count` is non-negative by its type and `Count <= size()` from
764     // the check above. So `0 <= size() - Count <= size()`, meaning
765     // `size() - Count` is a valid new size for `data()` and it will point to
766     // `Count` many elements.
767     return UNSAFE_BUFFERS(span<T, Count>(data() + (size() - Count), Count));
768   }
769 
770   // Returns a span over the first `count` elements.
771   //
772   // # Checks
773   // The function CHECKs that the span contains at least `count` elements and
774   // will terminate otherwise.
775   constexpr span<T> first(StrictNumeric<size_t> count) const noexcept {
776     CHECK_LE(size_t{count}, size());
777     // SAFETY: span provides that data() points to at least `size()` many
778     // elements. `count` is non-negative by its type and `count <= size()` from
779     // the CHECK above. So `count` is a valid new size for `data()`.
780     return UNSAFE_BUFFERS({data(), count});
781   }
782 
783   // Returns a span over the last `count` elements.
784   //
785   // # Checks
786   // The function CHECKs that the span contains at least `count` elements and
787   // will terminate otherwise.
788   constexpr span<T> last(StrictNumeric<size_t> count) const noexcept {
789     CHECK_LE(size_t{count}, size());
790     // SAFETY: span provides that data() points to at least `size()` many
791     // elements. `count` is non-negative by its type and `count <= size()` from
792     // the CHECK above. So `0 <= size() - count <= size()`, meaning
793     // `size() - count` is a valid new size for `data()` and it will point to
794     // `count` many elements.
795     return UNSAFE_BUFFERS({data() + (size() - size_t{count}), count});
796   }
797 
798   template <size_t Offset, size_t Count = dynamic_extent>
799   constexpr span<T, Count> subspan() const noexcept {
800     CHECK_LE(Offset, size());
801     CHECK(Count == dynamic_extent || Count <= size() - Offset);
802     const size_t new_extent = Count != dynamic_extent ? Count : size() - Offset;
803     // SAFETY: span provides that data() points to at least `size()` many
804     // elements.
805     //
806     // If Count is dynamic_extent, `new_extent` becomes `size() - Offset`. Since
807     // `Offset <= size()` from the check above, then `Offset` is a valid offset
808     // for data(), and `Offset + new_extent = Offset + size() - Offset = size()
809     // >= Offset` is also a valid offset that is not before `Offset`. This makes
810     // a span at `Offset` with size `new_extent` valid.
811     //
812     // Otherwise `Count <= size() - Offset` and `0 <= Offset <= size()` by the
813     // check above, so `Offset <= size() - Count` and `size() - Count` can not
814     // underflow. Then `Offset` is a valid offset for data() and `new_extent` is
815     // `Count <= size() - Offset`, so `Offset + extent <= Offset + size() -
816     // Offset = size()` which makes both `Offset` and `Offset + new_extent`
817     // valid offsets for data(), and since `new_extent` is non-negative, `Offset
818     // + new_extent` is not before `Offset` so `new_extent` is a valid size for
819     // the span at `data() + Offset`.
820     return UNSAFE_BUFFERS(span<T, Count>(data() + Offset, new_extent));
821   }
822 
823   // Returns a span over the first `count` elements starting at the given
824   // `offset` from the start of the span.
825   //
826   // # Checks
827   // The function CHECKs that the span contains at least `offset + count`
828   // elements, or at least `offset` elements if `count` is not specified, and
829   // will terminate otherwise.
830   constexpr span<T> subspan(size_t offset,
831                             size_t count = dynamic_extent) const noexcept {
832     CHECK_LE(offset, size());
833     CHECK(count == dynamic_extent || count <= size() - offset);
834     const size_t new_extent = count != dynamic_extent ? count : size() - offset;
835     // SAFETY: span provides that data() points to at least `size()` many
836     // elements.
837     //
838     // If count is dynamic_extent, `new_extent` becomes `size() - offset`. Since
839     // `offset <= size()` from the check above, then `offset` is a valid offset
840     // for data(), and `offset + new_extent = offset + size() - offset = size()
841     // >= offset` is also a valid offset that is not before `offset`. This makes
842     // a span at `offset` with size `new_extent` valid.
843     //
844     // Otherwise `count <= size() - offset` and `0 <= offset <= size()` by the
845     // checks above, so `offset <= size() - count` and `size() - count` can not
846     // underflow. Then `offset` is a valid offset for data() and `new_extent` is
847     // `count <= size() - offset`, so `offset + new_extent <= offset + size() -
848     // offset = size()` which makes both `offset` and `offset + new_extent`
849     // valid offsets for data(), and since `new_extent` is non-negative, `offset
850     // + new_extent` is not before `offset` so `new_extent` is a valid size for
851     // the span at `data() + offset`.
852     return UNSAFE_BUFFERS({data() + offset, new_extent});
853   }
854 
855   // Splits a span into two at the given `offset`, returning two spans that
856   // cover the full range of the original span.
857   //
858   // Similar to calling subspan() with the `offset` as the length on the first
859   // call, and then the `offset` as the offset in the second.
860   //
861   // The split_at<N>() overload allows construction of a fixed-size span from a
862   // compile-time constant. If the input span is fixed-size, both output output
863   // spans will be. Otherwise, the first will be fixed-size and the second will
864   // be dynamic-size.
865   //
866   // This is a non-std extension that  is inspired by the Rust slice::split_at()
867   // and split_at_mut() methods.
868   //
869   // # Checks
870   // The function CHECKs that the span contains at least `offset` elements and
871   // will terminate otherwise.
872   constexpr std::pair<span<T>, span<T>> split_at(size_t offset) const noexcept {
873     return {first(offset), subspan(offset)};
874   }
875 
876   // An overload of `split_at` which returns a fixed-size span.
877   //
878   // # Checks
879   // The function CHECKs that the span contains at least `Offset` elements and
880   // will terminate otherwise.
881   template <size_t Offset>
882   constexpr std::pair<span<T, Offset>, span<T>> split_at() const noexcept {
883     CHECK_LE(Offset, size());
884     return {first<Offset>(), subspan(Offset)};
885   }
886 
887   // [span.obs], span observers
888   constexpr size_t size() const noexcept { return size_; }
889   constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); }
890   [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
891 
892   // [span.elem], span element access
893   //
894   // # Checks
895   // The function CHECKs that the `idx` is inside the span and will terminate
896   // otherwise.
897   constexpr T& operator[](size_t idx) const noexcept {
898     CHECK_LT(idx, size());
899     // SAFETY: Since data() always points to at least `size()` elements, the
900     // check above ensures `idx < size()` and is thus in range for data().
901     return UNSAFE_BUFFERS(data()[idx]);
902   }
903 
904   // Returns a reference to the first element in the span.
905   //
906   // # Checks
907   // The function CHECKs that the span is not empty and will terminate
908   // otherwise.
909   constexpr T& front() const noexcept {
910     CHECK(!empty());
911     // SAFETY: Since data() always points to at least `size()` elements, the
912     // check above above ensures `0 < size()` and is thus in range for data().
913     return UNSAFE_BUFFERS(data()[0]);
914   }
915 
916   // Returns a reference to the last element in the span.
917   //
918   // # Checks
919   // The function CHECKs that the span is not empty and will terminate
920   // otherwise.
921   constexpr T& back() const noexcept {
922     CHECK(!empty());
923     // SAFETY: Since data() always points to at least `size()` elements, the
924     // check above above ensures `size() > 0` and thus `size() - 1` does not
925     // underflow and is in range for data().
926     return UNSAFE_BUFFERS(data()[size() - 1]);
927   }
928 
929   // Returns a pointer to the first element in the span. If the span is empty
930   // (`size()` is 0), the returned pointer may or may not be null, and it must
931   // not be dereferenced.
932   //
933   // It is always valid to add `size()` to the the pointer in C++ code, though
934   // it may be invalid in C code when the span is empty.
935   constexpr T* data() const noexcept { return data_; }
936 
937   // [span.iter], span iterator support
938   constexpr iterator begin() const noexcept {
939     // SAFETY: span provides that data() points to at least `size()` many
940     // elements, and size() is non-negative. So data() + size() is a valid
941     // pointer for the data() allocation.
942     return UNSAFE_BUFFERS(iterator(data(), data() + size()));
943   }
944 
945   constexpr iterator end() const noexcept {
946     // SAFETY: span provides that data() points to at least `size()` many
947     // elements, and size() is non-negative. So data() + size() is a valid
948     // pointer for the data() allocation.
949     return UNSAFE_BUFFERS(iterator(data(), data() + size(), data() + size()));
950   }
951 
952   constexpr reverse_iterator rbegin() const noexcept {
953     return reverse_iterator(end());
954   }
955 
956   constexpr reverse_iterator rend() const noexcept {
957     return reverse_iterator(begin());
958   }
959 
960   // Bounds-checked copy from a non-overlapping span. The spans must be the
961   // exact same size or a hard CHECK() occurs. If the two spans overlap,
962   // Undefined Behaviour occurs.
963   //
964   // This is a non-std extension that is inspired by the Rust
965   // slice::copy_from_slice() method.
966   //
967   // # Checks
968   // The function CHECKs that the `other` span has the same size as itself and
969   // will terminate otherwise.
970   constexpr void copy_from(span<const T> other)
971     requires(!std::is_const_v<T>)
972   {
973     CHECK_EQ(size_bytes(), other.size_bytes());
974     // Verify non-overlapping in developer builds.
975     //
976     // SAFETY: span provides that data() points to at least size() many
977     // elements, so adding size() to the data() pointer is well-defined.
978     DCHECK(UNSAFE_BUFFERS(data() + size()) <= other.data() ||
979            data() >= UNSAFE_BUFFERS(other.data() + other.size()));
980     // When compiling with -Oz, std::ranges::copy() does not get inlined, which
981     // makes copy_from() very expensive compared to memcpy for small sizes (up
982     // to around 4x slower). We observe that this is because ranges::copy() uses
983     // begin()/end() and span's iterators are checked iterators, not just
984     // pointers. This additional complexity prevents inlining and breaks the
985     // ability for the compiler to eliminate code.
986     //
987     // See also https://crbug.com/1396134.
988     //
989     // We also see std::copy() (with pointer arguments! not iterators) optimize
990     // and inline better than memcpy() since memcpy() needs to rely on
991     // size_bytes(), which while computable at compile time when `other` has a
992     // fixed size, the optimizer stumbles on with -Oz.
993     //
994     // SAFETY: The copy() here does not check bounds, but we have verified that
995     // `this` and `other` have the same bounds above (and are pointers of the
996     // same type), so `data()` and `other.data()` both have at least
997     // `other.size()` elements.
998     UNSAFE_BUFFERS(
999         std::copy(other.data(), other.data() + other.size(), data()));
1000   }
1001 
1002   // Compares two spans for equality by comparing the objects pointed to by the
1003   // spans. The operation is defined for spans of different types as long as the
1004   // types are themselves comparable.
1005   //
1006   // For primitive types, this replaces the less safe `memcmp` function, where
1007   // `memcmp(a.data(), b.data(), a.size())` can be written as `a == b` and can
1008   // no longer go outside the bounds of `b`. Otherwise, it replaced std::equal
1009   // or std::ranges::equal when working with spans, and when no projection is
1010   // needed.
1011   //
1012   // If the spans are of different sizes, they are not equal. If both spans are
1013   // empty, they are always equal (even though their data pointers may differ).
1014   //
1015   // # Implementation note
1016   // The non-template overloads allow implicit conversions to span for
1017   // comparison.
1018   friend constexpr bool operator==(span lhs, span rhs)
1019     requires(std::equality_comparable<const T>)
1020   {
1021     return internal::span_cmp(span<const T>(lhs), span<const T>(rhs));
1022   }
1023   friend constexpr bool operator==(span lhs, span<const T> rhs)
1024     requires(!std::is_const_v<T> && std::equality_comparable<const T>)
1025   {
1026     return internal::span_cmp(span<const T>(lhs), span<const T>(rhs));
1027   }
1028   template <class U, size_t M>
1029     requires(std::equality_comparable_with<const T, const U>)
1030   friend constexpr bool operator==(span lhs, span<U, M> rhs) {
1031     return internal::span_cmp(span<const T>(lhs), span<const U, M>(rhs));
1032   }
1033 
1034  private:
1035   // This field is not a raw_ptr<> since span is mostly used for stack
1036   // variables. Use `raw_span` instead for class fields, which does use
1037   // raw_ptr<> internally.
1038   InternalPtrType data_ = nullptr;
1039   size_t size_ = 0;
1040 };
1041 
1042 // [span.deduct], deduction guides.
1043 template <typename It, typename EndOrSize>
1044   requires(std::contiguous_iterator<It>)
1045 span(It, EndOrSize) -> span<std::remove_reference_t<std::iter_reference_t<It>>>;
1046 
1047 template <
1048     typename R,
1049     typename T = std::remove_reference_t<std::ranges::range_reference_t<R>>>
1050   requires(std::ranges::contiguous_range<R>)
1051 span(R&&)
1052     -> span<std::conditional_t<std::ranges::borrowed_range<R>, T, const T>,
1053             internal::ExtentV<R>>;
1054 
1055 // This guide prefers to let the contiguous_range guide match, since it can
1056 // produce a fixed-size span. Whereas, LegacyRange only produces a dynamic-sized
1057 // span.
1058 template <typename R>
1059   requires(!std::ranges::contiguous_range<R> && internal::LegacyRange<R>)
1060 span(R&& r) noexcept
1061     -> span<std::remove_reference_t<decltype(*std::ranges::data(r))>>;
1062 
1063 template <typename T, size_t N>
1064 span(const T (&)[N]) -> span<const T, N>;
1065 
1066 // [span.objectrep], views of object representation
1067 template <typename T, size_t X>
1068 constexpr auto as_bytes(span<T, X> s) noexcept {
1069   constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X;
1070   // SAFETY: span provides that data() points to at least size_bytes() many
1071   // bytes. So since `uint8_t` has a size of 1 byte, the size_bytes() value is
1072   // a valid size for a span at data() when viewed as `uint8_t*`.
1073   //
1074   // The reinterpret_cast is valid as the alignment of uint8_t (which is 1) is
1075   // always less-than or equal to the alignment of T.
1076   return UNSAFE_BUFFERS(span<const uint8_t, N>(
1077       reinterpret_cast<const uint8_t*>(s.data()), s.size_bytes()));
1078 }
1079 
1080 template <typename T, size_t X>
1081   requires(!std::is_const_v<T>)
1082 constexpr auto as_writable_bytes(span<T, X> s) noexcept {
1083   constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X;
1084   // SAFETY: span provides that data() points to at least size_bytes() many
1085   // bytes. So since `uint8_t` has a size of 1 byte, the size_bytes() value is a
1086   // valid size for a span at data() when viewed as `uint8_t*`.
1087   //
1088   // The reinterpret_cast is valid as the alignment of uint8_t (which is 1) is
1089   // always less-than or equal to the alignment of T.
1090   return UNSAFE_BUFFERS(
1091       span<uint8_t, N>(reinterpret_cast<uint8_t*>(s.data()), s.size_bytes()));
1092 }
1093 
1094 // as_chars() is the equivalent of as_bytes(), except that it returns a
1095 // span of const char rather than const uint8_t. This non-std function is
1096 // added since chrome still represents many things as char arrays which
1097 // rightfully should be uint8_t.
1098 template <typename T, size_t X>
1099 constexpr auto as_chars(span<T, X> s) noexcept {
1100   constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X;
1101   // SAFETY: span provides that data() points to at least size_bytes() many
1102   // bytes. So since `char` has a size of 1 byte, the size_bytes() value is a
1103   // valid size for a span at data() when viewed as `char*`.
1104   //
1105   // The reinterpret_cast is valid as the alignment of char (which is 1) is
1106   // always less-than or equal to the alignment of T.
1107   return UNSAFE_BUFFERS(span<const char, N>(
1108       reinterpret_cast<const char*>(s.data()), s.size_bytes()));
1109 }
1110 
1111 // as_string_view() converts a span over byte-sized primitives (holding chars or
1112 // uint8_t) into a std::string_view, where each byte is represented as a char.
1113 // It also accepts any type that can implicitly convert to a span, such as
1114 // arrays.
1115 //
1116 // If you want to view an arbitrary span type as a string, first explicitly
1117 // convert it to bytes via `base::as_bytes()`.
1118 //
1119 // For spans over byte-sized primitives, this is sugar for:
1120 // ```
1121 // std::string_view(as_chars(span).begin(), as_chars(span).end())
1122 // ```
1123 constexpr std::string_view as_string_view(span<const char> s) noexcept {
1124   return std::string_view(s.begin(), s.end());
1125 }
1126 constexpr std::string_view as_string_view(
1127     span<const unsigned char> s) noexcept {
1128   const auto c = as_chars(s);
1129   return std::string_view(c.begin(), c.end());
1130 }
1131 
1132 // as_writable_chars() is the equivalent of as_writable_bytes(), except that
1133 // it returns a span of char rather than uint8_t. This non-std function is
1134 // added since chrome still represents many things as char arrays which
1135 // rightfully should be uint8_t.
1136 template <typename T, size_t X>
1137   requires(!std::is_const_v<T>)
1138 auto as_writable_chars(span<T, X> s) noexcept {
1139   constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X;
1140   // SAFETY: span provides that data() points to at least size_bytes() many
1141   // bytes. So since `char` has a size of 1 byte, the size_bytes() value is
1142   // a valid size for a span at data() when viewed as `char*`.
1143   //
1144   // The reinterpret_cast is valid as the alignment of char (which is 1) is
1145   // always less-than or equal to the alignment of T.
1146   return UNSAFE_BUFFERS(
1147       span<char, N>(reinterpret_cast<char*>(s.data()), s.size_bytes()));
1148 }
1149 
1150 // Type-deducing helper for constructing a span.
1151 //
1152 // # Safety
1153 // The contiguous iterator `it` must point to the first element of at least
1154 // `size` many elements or Undefined Behaviour may result as the span may give
1155 // access beyond the bounds of the collection pointed to by `it`.
1156 template <int&... ExplicitArgumentBarrier, typename It>
1157 UNSAFE_BUFFER_USAGE constexpr auto make_span(
1158     It it,
1159     StrictNumeric<size_t> size) noexcept {
1160   using T = std::remove_reference_t<std::iter_reference_t<It>>;
1161   // SAFETY: The caller guarantees that `it` is the first of at least `size`
1162   // many elements.
1163   return UNSAFE_BUFFERS(span<T>(it, size));
1164 }
1165 
1166 // Type-deducing helper for constructing a span.
1167 //
1168 // # Checks
1169 // The function CHECKs that `it <= end` and will terminate otherwise.
1170 //
1171 // # Safety
1172 // The contiguous iterator `it` and its end sentinel `end` must be for the same
1173 // allocation or Undefined Behaviour may result as the span may give access
1174 // beyond the bounds of the collection pointed to by `it`.
1175 template <int&... ExplicitArgumentBarrier,
1176           typename It,
1177           typename End,
1178           typename = std::enable_if_t<!std::is_convertible_v<End, size_t>>>
1179 UNSAFE_BUFFER_USAGE constexpr auto make_span(It it, End end) noexcept {
1180   using T = std::remove_reference_t<std::iter_reference_t<It>>;
1181   // SAFETY: The caller guarantees that `it` and `end` are iterators of the
1182   // same allocation.
1183   return UNSAFE_BUFFERS(span<T>(it, end));
1184 }
1185 
1186 // make_span utility function that deduces both the span's value_type and extent
1187 // from the passed in argument.
1188 //
1189 // Usage: auto span = base::make_span(...);
1190 template <int&... ExplicitArgumentBarrier, typename Container>
1191 constexpr auto make_span(Container&& container) noexcept {
1192   using T =
1193       std::remove_pointer_t<decltype(std::data(std::declval<Container>()))>;
1194   using Extent = internal::Extent<Container>;
1195   return span<T, Extent::value>(std::forward<Container>(container));
1196 }
1197 
1198 // make_span utility function that allows callers to explicit specify the span's
1199 // extent, the value_type is deduced automatically. This is useful when passing
1200 // a dynamically sized container to a method expecting static spans, when the
1201 // container is known to have the correct size.
1202 //
1203 // Note: This will CHECK that N indeed matches size(container).
1204 //
1205 // # Usage
1206 // As this function is unsafe, the caller must guarantee that the size is
1207 // correct for the iterator, and will not allow the span to reach out of bounds.
1208 // ```
1209 // // SAFETY: <An explanation of how the size is checked/ensured to always be
1210 // // valid for the iterator>.
1211 // auto static_span = UNSAFE_BUFFERS(base::make_span<N>(it, size));
1212 // ```
1213 //
1214 // # Safety
1215 // The contiguous iterator `it` must point to the first element of at least
1216 // `size` many elements or Undefined Behaviour may result as the span may give
1217 // access beyond the bounds of the collection pointed to by `it`.
1218 template <size_t N, int&... ExplicitArgumentBarrier, typename It>
1219 UNSAFE_BUFFER_USAGE constexpr auto make_span(
1220     It it,
1221     StrictNumeric<size_t> size) noexcept {
1222   using T = std::remove_reference_t<std::iter_reference_t<It>>;
1223   // SAFETY: The caller guarantees that `it` is the first of at least `size`
1224   // many elements.
1225   return UNSAFE_BUFFERS(span<T, N>(it, size));
1226 }
1227 
1228 // make_span utility function that allows callers to explicit specify the span's
1229 // extent, the value_type is deduced automatically. This is useful when passing
1230 // a dynamically sized container to a method expecting static spans, when the
1231 // container is known to have the correct size.
1232 //
1233 // Note: This will CHECK that N indeed matches size(container).
1234 //
1235 // # Usage
1236 // As this function is unsafe, the caller must guarantee that the `end` is from
1237 // the same allocation as the `it` iterator.
1238 // ```
1239 // // SAFETY: <An explanation if non-trivial how the iterators are not from
1240 // // different containers/allocations>.
1241 // auto static_span = UNSAFE_BUFFERS(base::make_span<N>(it, end));
1242 // ```
1243 //
1244 // # Checks
1245 // The function CHECKs that `it <= end` and will terminate otherwise.
1246 //
1247 // # Safety
1248 // The contiguous iterator `it` and its end sentinel `end` must be for the same
1249 // allocation or Undefined Behaviour may result as the span may give access
1250 // beyond the bounds of the collection pointed to by `it`.
1251 template <size_t N,
1252           int&... ExplicitArgumentBarrier,
1253           typename It,
1254           typename End,
1255           typename = std::enable_if_t<!std::is_convertible_v<End, size_t>>>
1256 UNSAFE_BUFFER_USAGE constexpr auto make_span(It it, End end) noexcept {
1257   using T = std::remove_reference_t<std::iter_reference_t<It>>;
1258   // SAFETY: The caller guarantees that `it` and `end` are iterators of the
1259   // same allocation.
1260   return UNSAFE_BUFFERS(span<T, N>(it, end));
1261 }
1262 
1263 template <size_t N, int&... ExplicitArgumentBarrier, typename Container>
1264 constexpr auto make_span(Container&& container) noexcept {
1265   using T =
1266       std::remove_pointer_t<decltype(std::data(std::declval<Container>()))>;
1267   // SAFETY: The std::size() function gives the number of elements pointed to by
1268   // the std::data() function, which meets the requirement of span.
1269   return UNSAFE_BUFFERS(span<T, N>(std::data(container), std::size(container)));
1270 }
1271 
1272 // `span_from_ref` converts a reference to T into a span of length 1.  This is a
1273 // non-std helper that is inspired by the `std::slice::from_ref()` function from
1274 // Rust.
1275 template <typename T>
1276 constexpr span<T, 1u> span_from_ref(
1277     T& single_object ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept {
1278   // SAFETY: Given a valid reference to `single_object` the span of size 1 will
1279   // be a valid span that points to the `single_object`.
1280   return UNSAFE_BUFFERS(span<T, 1u>(std::addressof(single_object), 1u));
1281 }
1282 
1283 // `byte_span_from_ref` converts a reference to T into a span of uint8_t of
1284 // length sizeof(T).  This is a non-std helper that is a sugar for
1285 // `as_writable_bytes(span_from_ref(x))`.
1286 //
1287 // Const references are turned into a `span<const T, sizeof(T)>` while mutable
1288 // references are turned into a `span<T, sizeof(T)>`.
1289 template <typename T>
1290 constexpr span<const uint8_t, sizeof(T)> byte_span_from_ref(
1291     const T& single_object ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept {
1292   return as_bytes(span_from_ref(single_object));
1293 }
1294 template <typename T>
1295 constexpr span<uint8_t, sizeof(T)> byte_span_from_ref(
1296     T& single_object ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept {
1297   return as_writable_bytes(span_from_ref(single_object));
1298 }
1299 
1300 // Converts a string literal (such as `"hello"`) to a span of `char` while
1301 // omitting the terminating NUL character. These two are equivalent:
1302 // ```
1303 // base::span<char, 5u> s1 = base::span_from_cstring("hello");
1304 // base::span<char, 5u> s2 = base::span(std::string_view("hello"));
1305 // ```
1306 //
1307 // If you want to include the NUL terminator, then use the span constructor
1308 // directly, such as:
1309 // ```
1310 // base::span<char, 6u> s = base::span("hello");
1311 // ```
1312 template <size_t N>
1313 constexpr span<const char, N - 1> span_from_cstring(
1314     const char (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) {
1315   return span(lit).template first<N - 1>();
1316 }
1317 
1318 // Converts a string literal (such as `"hello"`) to a span of `uint8_t` while
1319 // omitting the terminating NUL character. These two are equivalent:
1320 // ```
1321 // base::span<uint8_t, 5u> s1 = base::byte_span_from_cstring("hello");
1322 // base::span<uint8_t, 5u> s2 = base::as_byte_span(std::string_view("hello"));
1323 // ```
1324 //
1325 // If you want to include the NUL terminator, then use the span constructor
1326 // directly, such as:
1327 // ```
1328 // base::span<uint8_t, 6u> s = base::as_bytes(base::span("hello"));
1329 // ```
1330 template <size_t N>
1331 constexpr span<const uint8_t, N - 1> byte_span_from_cstring(
1332     const char (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) {
1333   return as_bytes(span(lit).template first<N - 1>());
1334 }
1335 
1336 // Convenience function for converting an object which is itself convertible
1337 // to span into a span of bytes (i.e. span of const uint8_t). Typically used
1338 // to convert std::string or string-objects holding chars, or std::vector
1339 // or vector-like objects holding other scalar types, prior to passing them
1340 // into an API that requires byte spans.
1341 template <typename T>
1342   requires requires(const T& arg) {
1343     requires !std::is_array_v<std::remove_reference_t<T>>;
1344     make_span(arg);
1345   }
1346 constexpr span<const uint8_t> as_byte_span(const T& arg) {
1347   return as_bytes(make_span(arg));
1348 }
1349 
1350 // This overload for arrays preserves the compile-time size N of the array in
1351 // the span type signature span<uint8_t, N>.
1352 template <typename T, size_t N>
1353 constexpr span<const uint8_t, N * sizeof(T)> as_byte_span(
1354     const T (&arr ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) {
1355   return as_bytes(make_span<N>(arr));
1356 }
1357 
1358 // Convenience function for converting an object which is itself convertible
1359 // to span into a span of mutable bytes (i.e. span of uint8_t). Typically used
1360 // to convert std::string or string-objects holding chars, or std::vector
1361 // or vector-like objects holding other scalar types, prior to passing them
1362 // into an API that requires mutable byte spans.
1363 template <typename T>
1364   requires requires(T&& arg) {
1365     requires !std::is_array_v<std::remove_reference_t<T>>;
1366     make_span(arg);
1367     requires !std::is_const_v<typename decltype(make_span(arg))::element_type>;
1368   }
1369 constexpr span<uint8_t> as_writable_byte_span(T&& arg) {
1370   return as_writable_bytes(make_span(arg));
1371 }
1372 
1373 // This overload for arrays preserves the compile-time size N of the array in
1374 // the span type signature span<uint8_t, N>.
1375 template <typename T, size_t N>
1376   requires(!std::is_const_v<T>)
1377 constexpr span<uint8_t, N * sizeof(T)> as_writable_byte_span(
1378     T (&arr ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) {
1379   return as_writable_bytes(make_span<N>(arr));
1380 }
1381 template <typename T, size_t N>
1382   requires(!std::is_const_v<T>)
1383 constexpr span<uint8_t, N * sizeof(T)> as_writable_byte_span(
1384     T (&&arr ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) {
1385   return as_writable_bytes(make_span<N>(arr));
1386 }
1387 
1388 namespace internal {
1389 
1390 // Template helper for implementing operator==.
1391 template <class T, class U, size_t N, size_t M>
1392   requires((N == M || N == dynamic_extent || M == dynamic_extent) &&
1393            std::equality_comparable_with<T, U>)
1394 constexpr bool span_cmp(span<T, N> l, span<U, M> r) {
1395   return l.size() == r.size() && std::equal(l.begin(), l.end(), r.begin());
1396 }
1397 
1398 }  // namespace internal
1399 
1400 }  // namespace base
1401 
1402 template <typename T, size_t N, typename Ptr>
1403 inline constexpr bool
1404     std::ranges::enable_borrowed_range<base::span<T, N, Ptr>> = true;
1405 
1406 template <typename T, size_t N, typename Ptr>
1407 inline constexpr bool std::ranges::enable_view<base::span<T, N, Ptr>> = true;
1408 
1409 // EXTENT returns the size of any type that can be converted to a |base::span|
1410 // with definite extent, i.e. everything that is a contiguous storage of some
1411 // sort with static size. Specifically, this works for std::array in a constexpr
1412 // context. Note:
1413 //   * |std::size| should be preferred for plain arrays.
1414 //   * In run-time contexts, functions such as |std::array::size| should be
1415 //     preferred.
1416 #define EXTENT(x)                                                          \
1417   ::base::internal::must_not_be_dynamic_extent<decltype(::base::make_span( \
1418       x))::extent>()
1419 
1420 #endif  // BASE_CONTAINERS_SPAN_H_
1421