forked from qdrvm/kagome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuffer_or_view.hpp
123 lines (98 loc) · 2.93 KB
/
buffer_or_view.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <boost/variant/get.hpp>
#include <boost/variant/variant.hpp>
#include <type_traits>
#include "common/buffer.hpp"
namespace kagome::common {
/// Moved owned buffer or readonly view.
class BufferOrView {
using Span = std::span<const uint8_t>;
template <typename T>
using AsSpan = std::enable_if_t<std::is_convertible_v<T, Span>>;
struct Moved {};
public:
BufferOrView() = default;
~BufferOrView() = default;
BufferOrView(const BufferView &view) : variant{view} {}
template <size_t N>
BufferOrView(const std::array<uint8_t, N> &array)
: variant{BufferView(array)} {}
BufferOrView(const std::vector<uint8_t> &vector) = delete;
BufferOrView(std::vector<uint8_t> &&vector)
: variant{Buffer{std::move(vector)}} {}
BufferOrView(const BufferOrView &) = delete;
BufferOrView(BufferOrView &&) noexcept = default;
BufferOrView &operator=(const BufferOrView &) = delete;
BufferOrView &operator=(BufferOrView &&) = default;
/// Is buffer owned.
bool isOwned() const {
if (variant.index() == 2) {
throw std::logic_error{"Tried to use moved BufferOrView"};
}
return variant.index() == 1;
}
/// Get view.
BufferView view() const {
if (!isOwned()) {
return std::get<BufferView>(variant);
}
return BufferView{std::get<Buffer>(variant)};
}
/// Get view.
operator BufferView() const {
return view();
}
/// Data ptr for contiguous_range
auto data() const {
return view().data();
}
/// Size for sized_range
size_t size() const {
return view().size();
}
/// Iteratior begin for range
auto begin() const {
return view().begin();
}
/// Iteratior end for range
auto end() const {
return view().end();
}
/// Get mutable buffer reference. Copy once if view.
Buffer &mut() {
if (!isOwned()) {
auto view = std::get<BufferView>(variant);
variant = Buffer{view};
}
return std::get<Buffer>(variant);
}
/// Move buffer away. Copy once if view.
Buffer intoBuffer() & {
auto buffer = std::move(mut());
variant = Moved{};
return buffer;
}
/// Move buffer away. Copy once if view.
Buffer intoBuffer() && {
return std::move(mut());
}
private:
std::variant<BufferView, Buffer, Moved> variant;
template <typename T, typename = AsSpan<T>>
friend bool operator==(const BufferOrView &l, const T &r) {
return l.view() == Span{r};
}
template <typename T, typename = AsSpan<T>>
friend bool operator==(const T &l, const BufferOrView &r) {
return Span{l} == r.view();
}
};
} // namespace kagome::common
template <>
struct fmt::formatter<kagome::common::BufferOrView>
: fmt::formatter<kagome::common::BufferView> {};