// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_CONTAINERS_SPAN_OR_SIZE_H_ #define BASE_CONTAINERS_SPAN_OR_SIZE_H_ #include #include #include "base/containers/span.h" #include "base/functional/overloaded.h" #include "base/types/optional_ref.h" namespace base { // `SpanOrSize` contains either a `span` or just the size of data. This // is useful if the data is not retained in some scenarios, but size needs to be // available in all the scenarios. template class SpanOrSize { public: explicit constexpr SpanOrSize(base::span span) : span_or_size_(span) {} explicit constexpr SpanOrSize(size_t size) : span_or_size_(size) {} ~SpanOrSize() = default; // `SpanOrSize` is copyable and movable (just like `span` and `size_t`). SpanOrSize(const SpanOrSize&) = default; SpanOrSize& operator=(const SpanOrSize&) = default; SpanOrSize(SpanOrSize&&) = default; SpanOrSize& operator=(SpanOrSize&&) = default; constexpr T* ptr_or_null_if_no_data() const { return std::visit(Overloaded{ [](const base::span& span) { return span.data(); }, [](size_t size) -> T* { return nullptr; }, }, span_or_size_); } constexpr size_t size() const { return std::visit(Overloaded{ [](const base::span& span) { return span.size(); }, [](size_t size) { return size; }, }, span_or_size_); } constexpr optional_ref> span() const { return std::visit( Overloaded{ [](const base::span& span) { return optional_ref>(span); }, [](size_t size) { return optional_ref>(); }, }, span_or_size_); } private: std::variant, size_t> span_or_size_; }; } // namespace base #endif // BASE_CONTAINERS_SPAN_OR_SIZE_H_