• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 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_OR_SIZE_H_
6 #define BASE_CONTAINERS_SPAN_OR_SIZE_H_
7 
8 #include <stddef.h>
9 
10 #include <variant>
11 
12 #include "base/containers/span.h"
13 #include "base/functional/overloaded.h"
14 #include "base/types/optional_ref.h"
15 
16 namespace base {
17 
18 // `SpanOrSize<T>` contains either a `span<T>` or just the size of data.  This
19 // is useful if the data is not retained in some scenarios, but size needs to be
20 // available in all the scenarios.
21 template <typename T>
22 class SpanOrSize {
23  public:
SpanOrSize(base::span<T> span)24   explicit constexpr SpanOrSize(base::span<T> span) : span_or_size_(span) {}
SpanOrSize(size_t size)25   explicit constexpr SpanOrSize(size_t size) : span_or_size_(size) {}
26 
27   ~SpanOrSize() = default;
28 
29   // `SpanOrSize` is copyable and movable (just like `span` and `size_t`).
30   SpanOrSize(const SpanOrSize&) = default;
31   SpanOrSize& operator=(const SpanOrSize&) = default;
32   SpanOrSize(SpanOrSize&&) = default;
33   SpanOrSize& operator=(SpanOrSize&&) = default;
34 
ptr_or_null_if_no_data()35   constexpr T* ptr_or_null_if_no_data() const {
36     return std::visit(Overloaded{
37                           [](const base::span<T>& span) { return span.data(); },
38                           [](size_t size) -> T* { return nullptr; },
39                       },
40                       span_or_size_);
41   }
42 
size()43   constexpr size_t size() const {
44     return std::visit(Overloaded{
45                           [](const base::span<T>& span) { return span.size(); },
46                           [](size_t size) { return size; },
47                       },
48                       span_or_size_);
49   }
50 
span()51   constexpr optional_ref<const base::span<T>> span() const {
52     return std::visit(
53         Overloaded{
54             [](const base::span<T>& span) {
55               return optional_ref<const base::span<T>>(span);
56             },
57             [](size_t size) { return optional_ref<const base::span<T>>(); },
58         },
59         span_or_size_);
60   }
61 
62  private:
63   std::variant<base::span<T>, size_t> span_or_size_;
64 };
65 
66 }  // namespace base
67 
68 #endif  // BASE_CONTAINERS_SPAN_OR_SIZE_H_
69