LibQuicR
Loading...
Searching...
No Matches
track_name.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) 2024 Cisco Systems
2// SPDX-License-Identifier: BSD-2-Clause
3
4#pragma once
5
6#include "detail/span.h"
7#include "hash.h"
8
9#include <algorithm>
10#include <cstdint>
11#include <optional>
12#include <tuple>
13#include <vector>
14
15namespace quicr {
16
21 {
22 public:
23 TrackNamespace() = default;
24
31 template<typename... B,
32 std::enable_if_t<std::is_same_v<std::common_type_t<B...>, std::vector<uint8_t>>, bool> = true>
33 explicit TrackNamespace(B&&... entries)
34 {
35 static_assert(sizeof...(B) >= 1, "Track namespace must have at least 1 entry");
36 static_assert(sizeof...(B) <= 32 - 1, "Track namespace can only have a maximum of 32 entries");
37
38 std::size_t offset = 0;
39 const auto add_entry = [&](auto&& e) {
40 const auto& entry = entries_.emplace_back(Span{ bytes_ }.subspan(offset, e.size()));
41 hash_.emplace_back(quicr::hash({ entry.begin(), entry.end() }));
42
43 offset += e.size();
44 };
45
46 (bytes_.insert(bytes_.end(), entries.begin(), entries.end()), ...);
47 (add_entry(entries), ...);
48 }
49
56 template<typename... S, std::enable_if_t<std::is_same_v<std::common_type_t<S...>, std::string>, bool> = true>
57 explicit TrackNamespace(S&&... entries)
58 {
59 static_assert(sizeof...(S) >= 1, "Track namespace must have at least 1 entry");
60 static_assert(sizeof...(S) <= 32 - 1, "Track namespace can only have a maximum of 32 entries");
61
62 std::size_t offset = 0;
63 const auto add_entry = [&](auto&& e) {
64 const auto& entry = entries_.emplace_back(Span{ bytes_ }.subspan(offset, e.size()));
65 hash_.emplace_back(quicr::hash({ entry.begin(), entry.end() }));
66 offset += e.size();
67 };
68
69 (bytes_.insert(bytes_.end(), entries.begin(), entries.end()), ...);
70 (add_entry(entries), ...);
71 }
72
73 TrackNamespace(const std::vector<std::vector<uint8_t>>& entries)
74 : entries_(entries.size())
75 {
76 if (entries.size() > 32 || entries.size() == 0) {
77 throw std::invalid_argument("TrackNamespace requires a number of entries in the range of [1, 32]");
78 }
79
80 for (auto& entry : entries) {
81 bytes_.insert(bytes_.end(), entry.begin(), entry.end());
82 }
83
84 std::size_t offset = 0;
85 std::size_t i = 0;
86 for (auto& entry : entries) {
87 entries_[i] = Span{ bytes_ }.subspan(offset, entry.size());
88 hash_.emplace_back(quicr::hash(entry));
89 offset += entry.size();
90 ++i;
91 }
92 }
93
94 TrackNamespace(const std::vector<std::string>& entries)
95 : entries_(entries.size())
96 {
97 if (entries.size() > 32 || entries.size() == 0) {
98 throw std::invalid_argument("TrackNamespace requires a number of entries in the range of [1, 32]");
99 }
100
101 for (auto& entry : entries) {
102 bytes_.insert(bytes_.end(), entry.begin(), entry.end());
103 }
104
105 std::size_t offset = 0;
106 std::size_t i = 0;
107 for (auto& entry : entries) {
108 entries_[i] = Span{ bytes_ }.subspan(offset, entry.size());
109 hash_.emplace_back(quicr::hash(entries_[i]));
110 offset += entry.size();
111 ++i;
112 }
113 }
114
116 : bytes_(other.bytes_)
117 , entries_(other.entries_)
118 , hash_(other.hash_)
119 {
120 std::size_t offset = 0;
121 std::size_t i = 0;
122 for (auto& entry : entries_) {
123 entries_[i++] = Span{ bytes_ }.subspan(offset, entry.size());
124 offset += entry.size();
125 }
126 }
127
129 : bytes_(std::move(other.bytes_))
130 , entries_(std::move(other.entries_))
131 , hash_(std::move(other.hash_))
132 {
133 other.entries_.clear();
134
135 std::size_t offset = 0;
136 std::size_t i = 0;
137 for (auto& entry : entries_) {
138 entries_[i++] = Span{ bytes_ }.subspan(offset, entry.size());
139 offset += entry.size();
140 }
141 }
142
144 {
145 this->bytes_ = other.bytes_;
146 this->entries_ = other.entries_;
147 this->hash_ = other.hash_;
148
149 std::size_t offset = 0;
150 std::size_t i = 0;
151 for (auto& entry : entries_) {
152 entries_[i++] = Span{ bytes_ }.subspan(offset, entry.size());
153 offset += entry.size();
154 }
155
156 return *this;
157 }
158
160 {
161 this->bytes_ = std::move(other.bytes_);
162 this->entries_ = std::move(other.entries_);
163 this->hash_ = std::move(other.hash_);
164
165 std::size_t offset = 0;
166 std::size_t i = 0;
167 for (auto& entry : entries_) {
168 entries_[i++] = Span{ bytes_ }.subspan(offset, entry.size());
169 offset += entry.size();
170 }
171
172 return *this;
173 }
174
175 const std::vector<Span<const uint8_t>>& GetEntries() const noexcept { return entries_; }
176 const auto& GetHashes() const noexcept { return hash_; }
177
178 // NOLINTBEGIN(readability-identifier-naming)
179 auto begin() noexcept { return bytes_.begin(); }
180 auto end() noexcept { return bytes_.end(); }
181 auto begin() const noexcept { return bytes_.begin(); }
182 auto end() const noexcept { return bytes_.end(); }
183 auto data() const noexcept { return bytes_.data(); }
184 auto size() const noexcept { return bytes_.size(); }
185 bool empty() const noexcept { return bytes_.empty(); }
186 // NOLINTEND(readability-identifier-naming)
187
188 friend bool operator==(const TrackNamespace& lhs, const TrackNamespace& rhs) noexcept
189 {
190 return lhs.bytes_ == rhs.bytes_;
191 }
192
193 friend bool operator!=(const TrackNamespace& lhs, const TrackNamespace& rhs) noexcept { return !(lhs == rhs); }
194
195 friend bool operator<(const TrackNamespace& lhs, const TrackNamespace& rhs) noexcept
196 {
197 return lhs.bytes_ < rhs.bytes_;
198 }
199
200 friend bool operator>(const TrackNamespace& lhs, const TrackNamespace& rhs) noexcept
201 {
202 return lhs.bytes_ > rhs.bytes_;
203 }
204
205 friend bool operator<=(const TrackNamespace& lhs, const TrackNamespace& rhs) noexcept { return !(lhs > rhs); }
206
207 friend bool operator>=(const TrackNamespace& lhs, const TrackNamespace& rhs) noexcept { return !(lhs < rhs); }
208
209 bool IsPrefixOf(const TrackNamespace& other) const noexcept
210 {
211 if (this->hash_.size() > other.hash_.size()) {
212 return false;
213 }
214
215 for (size_t i = 0; i < this->hash_.size(); i++) {
216 if (this->hash_[i] != other.hash_[i]) {
217 return false;
218 }
219 }
220
221 return true;
222 }
223
224 bool HasSamePrefix(const TrackNamespace& other) const noexcept
225 {
226 const std::size_t prefix_size = std::min(this->hash_.size(), other.hash_.size());
227 for (size_t i = 0; i < prefix_size; i++) {
228 if (this->hash_[i] != other.hash_[i]) {
229 return false;
230 }
231 }
232
233 return true;
234 }
235
236 private:
237 uint64_t hash() const noexcept { return quicr::hash(bytes_); }
238
239 private:
240 std::vector<uint8_t> bytes_;
241 std::vector<Span<const uint8_t>> entries_;
242 std::vector<std::size_t> hash_;
243
244 friend struct std::hash<quicr::TrackNamespace>;
245 };
246}
247
248template<>
249struct std::hash<quicr::TrackNamespace>
250{
251 std::size_t operator()(const quicr::TrackNamespace& value) const noexcept { return value.hash(); }
252};
253
254namespace quicr {
255
256 using TrackNamespaceHash = uint64_t;
257 using TrackNameHash = uint64_t;
258 using TrackFullNameHash = uint64_t;
259
267 {
269 std::vector<uint8_t> name;
270 std::optional<uint64_t> track_alias;
271 };
272
274 {
275 TrackNamespaceHash track_namespace_hash = 0; // 64bit hash of namespace
276 TrackNameHash track_name_hash = 0; // 64bit hash of name
277
278 uint64_t track_fullname_hash = 0; // 62bit of namespace+name
279
280 TrackHash(const uint64_t name_space, const uint64_t name) noexcept
281 : track_namespace_hash{ name_space }
282 , track_name_hash{ name }
283 {
286
287 // TODO(tievens): Evaluate; change hash to be more than 62 bits to avoid collisions
289 }
290
291 TrackHash(const FullTrackName& ftn) noexcept
292 : track_namespace_hash{ hash({ ftn.name_space.begin(), ftn.name_space.end() }) }
293 , track_name_hash{ hash({ ftn.name.begin(), ftn.name.end() }) }
294 {
297
298 // TODO(tievens): Evaluate; change hash to be more than 62 bits to avoid collisions
300 }
301 };
302
303}
An N-tuple representation of a MOQ namespace.
Definition track_name.h:21
TrackNamespace(S &&... entries)
Constructs a namespace from a variadic number of string parameters.
Definition track_name.h:57
const auto & GetHashes() const noexcept
Definition track_name.h:176
auto data() const noexcept
Definition track_name.h:183
TrackNamespace(const std::vector< std::vector< uint8_t > > &entries)
Definition track_name.h:73
bool IsPrefixOf(const TrackNamespace &other) const noexcept
Definition track_name.h:209
TrackNamespace(const std::vector< std::string > &entries)
Definition track_name.h:94
friend bool operator==(const TrackNamespace &lhs, const TrackNamespace &rhs) noexcept
Definition track_name.h:188
auto size() const noexcept
Definition track_name.h:184
TrackNamespace & operator=(const TrackNamespace &other)
Definition track_name.h:143
bool empty() const noexcept
Definition track_name.h:185
friend bool operator>(const TrackNamespace &lhs, const TrackNamespace &rhs) noexcept
Definition track_name.h:200
friend bool operator!=(const TrackNamespace &lhs, const TrackNamespace &rhs) noexcept
Definition track_name.h:193
bool HasSamePrefix(const TrackNamespace &other) const noexcept
Definition track_name.h:224
friend bool operator<=(const TrackNamespace &lhs, const TrackNamespace &rhs) noexcept
Definition track_name.h:205
friend bool operator<(const TrackNamespace &lhs, const TrackNamespace &rhs) noexcept
Definition track_name.h:195
auto end() const noexcept
Definition track_name.h:182
friend bool operator>=(const TrackNamespace &lhs, const TrackNamespace &rhs) noexcept
Definition track_name.h:207
TrackNamespace(TrackNamespace &&other)
Definition track_name.h:128
const std::vector< Span< const uint8_t > > & GetEntries() const noexcept
Definition track_name.h:175
TrackNamespace(B &&... entries)
Constructs a namespace from a variadic number of Bytes parameters.
Definition track_name.h:33
TrackNamespace & operator=(TrackNamespace &&other)
Definition track_name.h:159
auto begin() noexcept
Definition track_name.h:179
TrackNamespace(const TrackNamespace &other)
Definition track_name.h:115
auto begin() const noexcept
Definition track_name.h:181
auto end() noexcept
Definition track_name.h:180
Definition transport.h:26
uint64_t TrackNameHash
Definition track_name.h:257
uint64_t TrackFullNameHash
Definition track_name.h:258
uint64_t TrackNamespaceHash
Definition track_name.h:256
void hash_combine(uint64_t &existing_hash, const uint64_t &add_hash)
Combine (aka add) hash to existing hash.
Definition hash.h:91
Full track name struct.
Definition track_name.h:267
std::vector< uint8_t > name
Definition track_name.h:269
TrackNamespace name_space
Definition track_name.h:268
std::optional< uint64_t > track_alias
Definition track_name.h:270
Definition track_name.h:274
uint64_t track_fullname_hash
Definition track_name.h:278
TrackNamespaceHash track_namespace_hash
Definition track_name.h:275
TrackHash(const uint64_t name_space, const uint64_t name) noexcept
Definition track_name.h:280
TrackHash(const FullTrackName &ftn) noexcept
Definition track_name.h:291
TrackNameHash track_name_hash
Definition track_name.h:276
std::size_t operator()(const quicr::TrackNamespace &value) const noexcept
Definition track_name.h:251