LeviLamina
Loading...
Searching...
No Matches
CompoundTagVariant.h
1#pragma once
2
3#include "mc/_HeaderOutputPredefine.h"
4
5#include "ll/api/Expected.h"
6#include "ll/api/base/Concepts.h"
7#include "ll/api/base/Meta.h"
8
9// auto generated inclusion list
10#include "mc/deps/nbt/ByteArrayTag.h"
11#include "mc/deps/nbt/ByteTag.h"
12#include "mc/deps/nbt/CompoundTag.h"
13#include "mc/deps/nbt/DoubleTag.h"
14#include "mc/deps/nbt/EndTag.h"
15#include "mc/deps/nbt/FloatTag.h"
16#include "mc/deps/nbt/Int64Tag.h"
17#include "mc/deps/nbt/IntArrayTag.h"
18#include "mc/deps/nbt/IntTag.h"
19#include "mc/deps/nbt/ListTag.h"
20#include "mc/deps/nbt/ShortTag.h"
21#include "mc/deps/nbt/StringTag.h"
22
23// auto generated forward declare list
24// clang-format off
25class Tag;
26// clang-format on
27
28class CompoundTagVariant {
29public:
30 // CompoundTagVariant inner types define
31 using Types = ::ll::meta::TypeList<
44
45 using Variant = Types::to<::std::variant>;
46 using string_t = std::string;
47
48 template <bool Const>
49 class Iterator {
50 public:
51 using iterator_category = std::bidirectional_iterator_tag;
52 using difference_type = ptrdiff_t;
53 using value_type = Tag;
54 using reference = std::conditional_t<Const, value_type const, value_type>&;
55 using pointer = std::add_pointer_t<reference>;
56
57 std::conditional_t<
58 Const,
59 std::variant<CompoundTagVariant const*, CompoundTag::const_iterator, ListTag::const_iterator>,
60 std::variant<CompoundTagVariant*, CompoundTag::iterator, ListTag::iterator>>
61 iter;
62
63 static Iterator makeBegin(auto& var) noexcept {
64 Iterator res;
65 switch (var.index()) {
66 case Tag::List:
67 res.iter.template emplace<2>(var.template get<ListTag>().begin());
68 break;
69 case Tag::Compound:
70 res.iter.template emplace<1>(var.template get<CompoundTag>().begin());
71 break;
72 case Tag::End:
73 res.iter.template emplace<0>(std::addressof(var) + 1);
74 break;
75 default:
76 res.iter.template emplace<0>(std::addressof(var));
77 }
78 return res;
79 }
80
81 static Iterator makeEnd(auto& var) noexcept {
82 Iterator res;
83 switch (var.index()) {
84 case Tag::List:
85 res.iter.template emplace<2>(var.template get<ListTag>().end());
86 break;
87 case Tag::Compound:
88 res.iter.template emplace<1>(var.template get<CompoundTag>().end());
89 break;
90 default:
91 res.iter.template emplace<0>(std::addressof(var) + 1);
92 }
93 return res;
94 }
95
96 [[nodiscard]] reference operator*() const noexcept {
97 switch (iter.index()) {
98 case 0:
99 return std::get<0>(iter)->get();
100 case 1:
101 return std::get<1>(iter)->second.get();
102 case 2:
103 return *std::get<2>(iter)->get();
104 default:
105 LL_UNREACHABLE;
106 }
107 LL_UNREACHABLE;
108 }
109
110 [[nodiscard]] pointer operator->() const noexcept { return std::addressof(**this); }
111
112 Iterator& operator++() noexcept {
113 std::visit([](auto& val) { ++val; }, iter);
114 return *this;
115 }
116
117 Iterator operator++(int) noexcept {
118 Iterator tmp = *this;
119 ++*this;
120 return tmp;
121 }
122
123 Iterator& operator--() noexcept {
124 std::visit([](auto& val) { --val; }, iter);
125 return *this;
126 }
127
128 Iterator operator--(int) noexcept {
129 Iterator tmp = *this;
130 --*this;
131 return tmp;
132 }
133
134 [[nodiscard]] bool operator==(Iterator const& r) const noexcept { return this->iter == r.iter; }
135 };
136
137 using iterator = Iterator<false>;
138 using const_iterator = Iterator<true>;
139
140public:
141 // member variables
142 Variant mTagStorage;
143
144public:
145 LLNDAPI static ll::Expected<CompoundTagVariant>
146 parse(std::string_view snbt, optional_ref<size_t> parsedLength = std::nullopt) noexcept;
147
148 [[nodiscard]] constexpr CompoundTagVariant() = default;
149
150 [[nodiscard]] constexpr CompoundTagVariant(CompoundTagVariant&&) = default;
151
152 LL_MAY_CONSTEXPR CompoundTagVariant& operator=(CompoundTagVariant&&) = default;
153
154 [[nodiscard]] constexpr CompoundTagVariant(CompoundTagVariant const&) = default;
155
156 LL_MAY_CONSTEXPR CompoundTagVariant& operator=(CompoundTagVariant const&) = default;
157
158 template <class T>
159 requires(requires(T o) { mTagStorage = std::move(o); })
160 constexpr CompoundTagVariant& operator=(T other) {
161 mTagStorage = std::move(other);
162 return *this;
163 }
164
165 [[nodiscard]] constexpr CompoundTagVariant(std::nullptr_t) {}
166
167 [[nodiscard]] bool operator==(CompoundTagVariant const& other) const { return get() == other.get(); }
168
169 [[nodiscard]] CompoundTagVariant(Variant tag) : mTagStorage(std::move(tag)) {}
170
171 template <class T, class... Args>
172 [[nodiscard]] constexpr CompoundTagVariant(std::in_place_type_t<T>, Args&&... args)
173 : mTagStorage(std::in_place_type<T>, std::forward<Args>(args)...) {}
174
175 [[nodiscard]] constexpr CompoundTagVariant(std::initializer_list<CompoundTag::TagMap::value_type> tagPairs)
176 : mTagStorage(std::in_place_type<CompoundTag>, tagPairs) {}
177
178 [[nodiscard]] CompoundTagVariant(UniqueTagPtr&& tag) {
179 if (!tag) {
180 return;
181 }
182 ::ll::meta::visitIndex<Types::size>(static_cast<size_t>(tag->getId()), [&]<size_t I> {
183 mTagStorage = std::move((Types::get<I>&)*tag);
184 });
185 }
186 [[nodiscard]] CompoundTagVariant(UniqueTagPtr const& tag) : CompoundTagVariant(tag ? tag->copy() : nullptr) {}
187 template <std::derived_from<Tag> T>
188 [[nodiscard]] constexpr CompoundTagVariant(T tag) : mTagStorage(std::move(tag)) {}
189 template <std::integral T>
190 [[nodiscard]] constexpr CompoundTagVariant(T integer) {
191 constexpr size_t size = sizeof(T);
192 if constexpr (size == 1) {
193 mTagStorage = ByteTag{integer};
194 } else if constexpr (size == 2) {
195 mTagStorage = ShortTag{integer};
196 } else if constexpr (size == 4) {
197 mTagStorage = IntTag{integer};
198 } else {
199 mTagStorage = Int64Tag{integer};
200 }
201 }
202 [[nodiscard]] CompoundTagVariant(std::byte b) : mTagStorage(ByteTag{b}) {}
203
204 [[nodiscard]] CompoundTagVariant(float f) : mTagStorage(FloatTag{f}) {}
205
206 [[nodiscard]] CompoundTagVariant(double d) : mTagStorage(DoubleTag{d}) {}
207
208 [[nodiscard]] constexpr CompoundTagVariant(std::string s)
209 : mTagStorage(std::in_place_type<StringTag>, std::move(s)) {}
210
211 [[nodiscard]] constexpr CompoundTagVariant(std::string_view s) : mTagStorage(std::in_place_type<StringTag>, s) {}
212
213 template <size_t N>
214 [[nodiscard]] constexpr CompoundTagVariant(char const (&str)[N])
215 : CompoundTagVariant(std::string_view{str, N - 1}) {}
216
217 [[nodiscard]] iterator begin() noexcept { return iterator::makeBegin(*this); }
218 [[nodiscard]] const_iterator begin() const noexcept { return cbegin(); }
219 [[nodiscard]] const_iterator cbegin() const noexcept { return const_iterator::makeBegin(*this); }
220
221 [[nodiscard]] iterator end() noexcept { return iterator::makeEnd(*this); }
222 [[nodiscard]] const_iterator end() const noexcept { return cend(); }
223 [[nodiscard]] const_iterator cend() const noexcept { return const_iterator::makeEnd(*this); }
224
225 [[nodiscard]] constexpr Tag::Type index() const noexcept { return Tag::Type(mTagStorage.index()); }
226 [[nodiscard]] constexpr Tag::Type getId() const noexcept { return index(); }
227
228 template <std::derived_from<Tag> T>
229 [[nodiscard]] constexpr bool hold() const noexcept {
230 return std::holds_alternative<T>(mTagStorage);
231 }
232 [[nodiscard]] constexpr bool hold(::Tag::Type type) const noexcept { return getId() == type; }
233
234 // consistency with json
235 [[nodiscard]] constexpr bool is_array() const noexcept { return hold(Tag::List); }
236 [[nodiscard]] constexpr bool is_binary() const noexcept { return hold(Tag::ByteArray) || hold(Tag::IntArray); }
237 [[nodiscard]] constexpr bool is_boolean() const noexcept { return hold(Tag::Byte); }
238 [[nodiscard]] constexpr bool is_null() const noexcept { return hold(Tag::End); }
239 [[nodiscard]] constexpr bool is_number_float() const noexcept { return hold(Tag::Float) || hold(Tag::Double); }
240 [[nodiscard]] constexpr bool is_number_integer() const noexcept {
241 return hold(Tag::Byte) || hold(Tag::Short) || hold(Tag::Int) || hold(Tag::Int64);
242 }
243 [[nodiscard]] constexpr bool is_number_signed() const noexcept { return is_number_integer(); }
244 [[nodiscard]] constexpr bool is_number_unsigned() const noexcept { return false; }
245 [[nodiscard]] constexpr bool is_object() const noexcept { return hold(Tag::Compound); }
246 [[nodiscard]] constexpr bool is_string() const noexcept { return hold(Tag::String); }
247 [[nodiscard]] constexpr bool is_number() const noexcept { return is_number_float() || is_number_integer(); }
248 [[nodiscard]] constexpr bool is_primitive() const noexcept {
249 return is_null() || is_string() || is_number() || is_binary();
250 }
251 [[nodiscard]] constexpr bool is_structured() const noexcept { return is_array() || is_object(); }
252
253 [[nodiscard]] constexpr std::string_view type_name() const noexcept {
254 if (is_null()) return "null";
255 if (is_object()) return "object";
256 if (is_array()) return "array";
257 if (is_string()) return "string";
258 if (is_boolean()) return "boolean";
259 if (is_number()) return "number";
260 if (is_binary()) return "binary";
261 return "unknown";
262 }
263
264 [[nodiscard]] constexpr CompoundTag::TagMap const& items() const { return get<CompoundTag>().mTags; }
265 [[nodiscard]] constexpr CompoundTag::TagMap& items() { return get<CompoundTag>().mTags; }
266
267 [[nodiscard]] bool contains(std::string_view key) const noexcept {
268 if (is_object()) {
269 return get<CompoundTag>().contains(key);
270 }
271 return false;
272 }
273
274 [[nodiscard]] bool contains(std::string_view key, Tag::Type type) const noexcept {
275 if (is_object()) {
276 return get<CompoundTag>().contains(key, type);
277 }
278 return false;
279 }
280
281 template <std::derived_from<Tag> T>
282 [[nodiscard]] bool contains(std::string_view key) const noexcept {
283 constexpr size_t idx = Types::index<T>;
284 return contains(key, (Tag::Type)idx);
285 }
286
287 [[nodiscard]] constexpr size_t size() const noexcept {
288 switch (index()) {
289 case Tag::Byte:
290 case Tag::Short:
291 case Tag::Int:
292 case Tag::Int64:
293 case Tag::Float:
294 case Tag::Double:
295 case Tag::String:
296 return 1;
297 case Tag::List:
298 return get<ListTag>().size();
299 case Tag::Compound:
300 return get<CompoundTag>().size();
301 case Tag::IntArray:
302 return get<IntArrayTag>().size();
303 case Tag::ByteArray:
304 return get<ByteArrayTag>().size();
305 case Tag::End:
306 return 0;
307 default:
308 LL_UNREACHABLE;
309 }
310 }
311
312 template <std::derived_from<Tag> T>
313 [[nodiscard]] constexpr T& get() {
314 return std::get<T>(mTagStorage);
315 }
316
317 template <std::derived_from<Tag> T>
318 [[nodiscard]] constexpr T const& get() const {
319 return std::get<T>(mTagStorage);
320 }
321
322 template <class Ref>
323 [[nodiscard]] constexpr Ref get_ref() &
324 requires(std::same_as<Ref, string_t&>)
325 {
326 return static_cast<string_t&>(get<StringTag>());
327 }
328
329 template <class Ref>
330 [[nodiscard]] constexpr Ref get_ref() const&
331 requires(std::same_as<Ref, string_t const&>)
332 {
333 return static_cast<string_t const&>(get<StringTag>());
334 }
335
336 template <class T>
337 requires(std::is_arithmetic_v<T> && !ll::traits::is_char_v<T>)
338 [[nodiscard]] constexpr T get() const {
339 return static_cast<T>(*this);
340 }
341
342 [[nodiscard]] Tag& get() { return reinterpret_cast<Tag&>(mTagStorage); }
343
344 [[nodiscard]] Tag const& get() const { return reinterpret_cast<Tag const&>(mTagStorage); }
345
346 template <std::derived_from<Tag> T>
347 constexpr T& emplace() {
348 return mTagStorage.emplace<T>();
349 }
350
351 [[nodiscard]] UniqueTagPtr& operator[](size_t index) {
352 if (hold(Tag::List)) {
353 return get<ListTag>()[index];
354 } else {
355 throw std::runtime_error("tag not hold an array");
356 }
357 }
358
359 [[nodiscard]] UniqueTagPtr const& operator[](size_t index) const {
360 if (hold(Tag::List)) {
361 return get<ListTag>()[index];
362 } else {
363 throw std::runtime_error("tag not hold an array");
364 }
365 }
366
367 [[nodiscard]] CompoundTagVariant& operator[](std::string_view index) {
368 if (is_null()) {
369 mTagStorage = CompoundTag{};
370 }
371 if (!hold(Tag::Compound)) {
372 throw std::runtime_error("tag not hold an object");
373 }
374 return get<CompoundTag>()[index];
375 }
376
377 [[nodiscard]] CompoundTagVariant const& operator[](std::string_view index) const {
378 if (!hold(Tag::Compound)) {
379 throw std::runtime_error("tag not hold an object");
380 }
381 return get<CompoundTag>()[index];
382 }
383
384 template <size_t N>
385 [[nodiscard]] CompoundTagVariant& operator[](char const (&index)[N]) { // make EDG happy
386 return operator[](std::string_view{index, N - 1});
387 }
388
389 template <size_t N>
390 [[nodiscard]] CompoundTagVariant const& operator[](char const (&index)[N]) const { // make EDG happy
391 return operator[](std::string_view{index, N - 1});
392 }
393
394 [[nodiscard]] UniqueTagPtr toUniqueCopy() const& {
395 return std::visit(
396 [](auto& val) -> std::unique_ptr<Tag> { return std::make_unique<std::decay_t<decltype(val)>>(val); },
397 mTagStorage
398 );
399 }
400
401 [[nodiscard]] UniqueTagPtr toUnique() && {
402 return std::visit(
403 [](auto&& val) -> std::unique_ptr<Tag> {
404 return std::make_unique<std::decay_t<decltype(val)>>(std::move(val));
405 },
406 mTagStorage
407 );
408 }
409
410 LLNDAPI std::string toSnbt(SnbtFormat snbtFormat = SnbtFormat::PrettyFilePrint, uchar indent = 4) const noexcept;
411
412 std::string dump(uchar indent = 4, SnbtFormat snbtFormat = SnbtFormat::PrettyFilePrint) const noexcept {
413 return toSnbt(snbtFormat, indent);
414 }
415
416 void push_back(CompoundTagVariant val) {
417 if (is_null()) {
418 mTagStorage = ListTag{};
419 }
420 if (!hold(Tag::List)) {
421 throw std::runtime_error("tag not hold an array");
422 }
423 get<ListTag>().add(std::move(val).toUnique());
424 }
425
426 template <class T>
427 requires(std::is_arithmetic_v<T> && !ll::traits::is_char_v<T>)
428 [[nodiscard]] constexpr operator T() const {
429 if (is_number()) {
430 return std::visit(
431 [](auto& val) -> T {
432 if constexpr (std::is_convertible_v<std::decay_t<decltype(val)>, T>) {
433 return (T)val;
434 } else {
435 return {};
436 }
437 },
438 mTagStorage
439 );
440 } else {
441 throw std::runtime_error("tag not hold an number");
442 }
443 }
444 [[nodiscard]] operator std::string const&() const { return get<StringTag>(); }
445 [[nodiscard]] operator std::string&() { return get<StringTag>(); }
446 [[nodiscard]] operator std::string&&() && { return std::move(get<StringTag>()); }
447 [[nodiscard]] operator std::string_view() const { return get<StringTag>(); }
448 static CompoundTagVariant object(std::initializer_list<CompoundTag::TagMap::value_type> init = {}) {
449 return CompoundTagVariant{std::in_place_type<CompoundTag>, init};
450 }
451 static CompoundTagVariant array(std::initializer_list<CompoundTagVariant> init = {}) {
452 return CompoundTagVariant{std::in_place_type<ListTag>, init};
453 }
454};
455
456[[nodiscard]] inline auto CompoundTag::begin() noexcept { return mTags.begin(); }
457[[nodiscard]] inline auto CompoundTag::begin() const noexcept { return mTags.begin(); }
458[[nodiscard]] inline auto CompoundTag::end() noexcept { return mTags.end(); }
459[[nodiscard]] inline auto CompoundTag::end() const noexcept { return mTags.end(); }
460[[nodiscard]] inline auto CompoundTag::rbegin() noexcept { return mTags.rbegin(); }
461[[nodiscard]] inline auto CompoundTag::rbegin() const noexcept { return mTags.rbegin(); }
462[[nodiscard]] inline auto CompoundTag::rend() noexcept { return mTags.rend(); }
463[[nodiscard]] inline auto CompoundTag::rend() const noexcept { return mTags.rend(); }
464[[nodiscard]] inline auto CompoundTag::cbegin() const noexcept { return mTags.cbegin(); }
465[[nodiscard]] inline auto CompoundTag::cend() const noexcept { return mTags.cend(); }
466[[nodiscard]] inline auto CompoundTag::crbegin() const noexcept { return mTags.crbegin(); }
467[[nodiscard]] inline auto CompoundTag::crend() const noexcept { return mTags.crend(); }
468inline bool CompoundTag::erase(std::string_view name) {
469 if (auto it = mTags.find(name); it != mTags.end()) {
470 mTags.erase(it);
471 return true;
472 }
473 return false;
474}
475[[nodiscard]] inline CompoundTagVariant& CompoundTag::operator[](std::string_view index) {
476 if (auto it = mTags.find(index); it != mTags.end()) {
477 return it->second;
478 }
479 return mTags[std::string{index}];
480}
481[[nodiscard]] inline CompoundTagVariant const& CompoundTag::operator[](std::string_view index) const {
482 if (auto it = mTags.find(index); it != mTags.end()) {
483 return it->second;
484 }
485 throw std::out_of_range("invalid nbt key");
486}
487inline void CompoundTag::rename(std::string_view name, std::string_view newName) {
488 if (auto it = mTags.find(name); it != mTags.end()) {
489 CompoundTagVariant tmp{std::move(it->second)};
490 mTags.erase(it);
491 mTags.try_emplace(std::string{newName}, std::move(tmp));
492 }
493}
494
495[[nodiscard]] constexpr ListTag::ListTag(std::vector<CompoundTagVariant> tags) {
496 if (tags.empty()) {
497 mType = Tag::End;
498 } else {
499 mType = tags.front().index();
500 reserve(tags.size());
501 for (auto& tag : tags) {
502 emplace_back(std::move(tag).toUnique());
503 }
504 }
505}
506[[nodiscard]] constexpr ListTag::ListTag(std::initializer_list<CompoundTagVariant> tags) {
507 if (tags.size() == 0) {
508 mType = Tag::End;
509 } else {
510 mType = tags.begin()->index();
511 reserve(tags.size());
512 for (auto& tag : tags) {
513 emplace_back(tag.toUniqueCopy());
514 }
515 }
516}
517[[nodiscard]] inline bool operator==(UniqueTagPtr const& l, CompoundTagVariant const& r) {
518 return l ? (*l == r.get()) : false;
519}
520[[nodiscard]] inline bool operator==(CompoundTagVariant const& l, UniqueTagPtr const& r) {
521 return r ? (l.get() == *r) : false;
522}
523
524[[nodiscard]] inline UniqueTagPtr::UniqueTagPtr(CompoundTagVariant&& r) : ptr(std::move(r).toUnique().release()) {}
525
526[[nodiscard]] inline UniqueTagPtr::UniqueTagPtr(CompoundTagVariant const& r) : ptr(r.toUniqueCopy().release()) {}
527
528inline UniqueTagPtr& UniqueTagPtr::operator=(CompoundTagVariant&& r) {
529 reset(std::move(r).toUnique().release());
530 return *this;
531}
532inline UniqueTagPtr& UniqueTagPtr::operator=(CompoundTagVariant const& r) {
533 reset(r.toUniqueCopy().release());
534 return *this;
535}
536
537template <std::derived_from<Tag> T>
538[[nodiscard]] inline T& UniqueTagPtr::get() const {
539 if (hold<T>()) {
540 return *static_cast<T*>(ptr);
541 }
542 throw std::runtime_error("not the expected type");
543}
544[[nodiscard]] inline bool UniqueTagPtr::contains(std::string_view key) const noexcept {
545 if (is_object()) {
546 return get<CompoundTag>().contains(key);
547 }
548 return false;
549}
550[[nodiscard]] inline bool UniqueTagPtr::contains(std::string_view key, Tag::Type type) const noexcept {
551 if (is_object()) {
552 return get<CompoundTag>().contains(key, type);
553 }
554 return false;
555}
556[[nodiscard]] inline size_t UniqueTagPtr::size() const noexcept {
557 switch (index()) {
558 case Tag::Byte:
559 case Tag::Short:
560 case Tag::Int:
561 case Tag::Int64:
562 case Tag::Float:
563 case Tag::Double:
564 case Tag::String:
565 return 1;
566 case Tag::List:
567 return get<ListTag>().size();
568 case Tag::Compound:
569 return get<CompoundTag>().size();
570 case Tag::IntArray:
571 return get<IntArrayTag>().size();
572 case Tag::ByteArray:
573 return get<ByteArrayTag>().size();
574 case Tag::End:
575 return 0;
576 default:
577 LL_UNREACHABLE;
578 }
579}
580[[nodiscard]] inline UniqueTagPtr::operator std::string const&() const { return get<StringTag>(); }
581[[nodiscard]] inline UniqueTagPtr::operator std::string&() & { return get<StringTag>(); }
582[[nodiscard]] inline UniqueTagPtr::operator std::string&&() && { return std::move(get<StringTag>()); }
583[[nodiscard]] inline UniqueTagPtr::operator std::string_view() const { return get<StringTag>(); }
584
585[[nodiscard]] inline UniqueTagPtr& UniqueTagPtr::operator[](size_t index) {
586 if (hold(Tag::List)) {
587 return get<ListTag>()[index];
588 } else {
589 throw std::runtime_error("tag not hold an array");
590 }
591}
592[[nodiscard]] inline UniqueTagPtr const& UniqueTagPtr::operator[](size_t index) const {
593 if (hold(Tag::List)) {
594 return get<ListTag>()[index];
595 } else {
596 throw std::runtime_error("tag not hold an array");
597 }
598}
599[[nodiscard]] inline CompoundTagVariant& UniqueTagPtr::operator[](std::string_view index) {
600 if (is_null()) {
601 emplace<CompoundTag>();
602 }
603 if (!hold(Tag::Compound)) {
604 throw std::runtime_error("tag not hold an object");
605 }
606 return get<CompoundTag>()[index];
607}
608[[nodiscard]] inline CompoundTagVariant const& UniqueTagPtr::operator[](std::string_view index) const {
609 if (!hold(Tag::Compound)) {
610 throw std::runtime_error("tag not hold an object");
611 }
612 return get<CompoundTag>()[index];
613}
614template <class T>
615 requires(std::is_arithmetic_v<T> && !ll::traits::is_char_v<T>)
616[[nodiscard]] inline UniqueTagPtr::operator T() const {
617 if (is_number()) {
618 return ll::meta::visitIndex<CompoundTagVariant::Types::size>((size_t)getId(), [&]<size_t I>() -> T {
619 auto& val = *static_cast<CompoundTagVariant::Types::get<I>*>(ptr);
620 if constexpr (std::is_convertible_v<std::decay_t<decltype(val)>, T>) {
621 return (T)val;
622 } else {
623 return {};
624 }
625 });
626 } else {
627 throw std::runtime_error("tag not hold an number");
628 }
629}
Definition ByteArrayTag.h:9
Definition ByteTag.h:15
Definition CompoundTagVariant.h:49
Definition CompoundTagVariant.h:28
Definition CompoundTag.h:18
Definition DoubleTag.h:9
Definition EndTag.h:9
Definition FloatTag.h:15
Definition Int64Tag.h:9
Definition IntArrayTag.h:9
Definition IntTag.h:15
Definition ListTag.h:19
Definition ShortTag.h:9
Definition StringTag.h:15
Definition Tag.h:42
Definition UniqueTagPtr.h:22
Definition Meta.h:197
Definition optional_ref.h:10
STL namespace.