blob: 0efc131fb199745e1d452ebfacd915c397063889 [file] [log] [blame]
mark a. foltzeca304d2023-01-25 13:45:44 -08001// Copyright 2023 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 PLATFORM_BASE_BYTE_VIEW_H_
6#define PLATFORM_BASE_BYTE_VIEW_H_
7
8#include <stddef.h>
9
10#include <cassert>
11#include <cstddef>
12#include <cstdint>
13#include <vector>
14
15#include "platform/base/macros.h"
16
17namespace openscreen {
18
19// Contains a pointer and length to a span of continguous and unowned bytes.
20// The underlying data cannot be modified.
21//
22// The API is a slimmed-down version of a C++20 std::span<const uint8_t> and is
23// intended to be forwards-compatible. Support for iterators and front/back can
24// be added as needed; we don't intend to add support for static extents.
25//
mark a. foltzccc269d2023-01-31 10:28:21 -080026// NOTES:
27// - Although other span implementations allow passing zero to last(), we do
28// not, as the behavior is undefined. Callers should explicitly create an
29// empty ByteView instead.
mark a. foltzeca304d2023-01-25 13:45:44 -080030//
mark a. foltzccc269d2023-01-31 10:28:21 -080031// - operator== is not implemented to align with std::span. For more
32// discussion, this blog post has considerations when implementing operators
33// on types that don't own the data they depend upon:
34// https://abseil.io/blog/20180531-regular-types
35//
36// - Unit tests that want to compare the bytes behind two ByteViews can use
37// ExpectByteViewsHaveSameBytes().
38//
mark a. foltzeca304d2023-01-25 13:45:44 -080039class ByteView {
40 public:
41 constexpr ByteView() noexcept = default;
42 constexpr ByteView(const uint8_t* data, size_t count)
43 : data_(data), count_(count) {}
44 explicit ByteView(const std::vector<uint8_t>& v)
45 : data_(v.data()), count_(v.size()) {}
46
47 constexpr ByteView(const ByteView&) noexcept = default;
48 constexpr ByteView& operator=(const ByteView&) noexcept = default;
49 ByteView(ByteView&&) noexcept = default;
50 ByteView& operator=(ByteView&&) noexcept = default;
51 ~ByteView() = default;
52
53 constexpr const uint8_t* data() const noexcept { return data_; }
54
55 constexpr const uint8_t& operator[](size_t idx) const {
56 assert(idx < count_);
57 return *(data_ + idx);
58 }
59
60 constexpr size_t size() const { return count_; }
61
62 [[nodiscard]] constexpr bool empty() const { return count_ == 0; }
63
64 constexpr ByteView first(size_t count) const {
65 assert(count <= count_);
66 return ByteView(data_, count);
67 }
68
69 constexpr ByteView last(size_t count) const {
70 assert(count <= count_);
71 assert(count != 0);
72 return ByteView(data_ + (count_ - count), count);
73 }
74
75 constexpr const uint8_t* begin() const noexcept { return data_; }
76 constexpr const uint8_t* end() const noexcept { return data_ + count_; }
77
78 void remove_prefix(size_t count) noexcept {
79 assert(count_ >= count);
80 data_ += count;
81 count_ -= count;
82 }
83
84 void remove_suffix(size_t count) noexcept {
85 assert(count_ >= count);
86 count_ -= count;
87 }
88
89 constexpr ByteView subspan(size_t offset, size_t count) const {
90 assert(offset + count < count_);
91 return ByteView(data_ + offset, count);
92 }
93
94 private:
95 const uint8_t* data_{nullptr};
96 size_t count_{0};
97};
98
99} // namespace openscreen
100
101#endif // PLATFORM_BASE_BYTE_VIEW_H_