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