28class CompoundTagVariant {
45 using Variant = Types::to<::std::variant>;
50 using iterator_category = std::bidirectional_iterator_tag;
51 using difference_type = ptrdiff_t;
52 using value_type =
Tag;
53 using reference = std::conditional_t<Const, value_type const, value_type>&;
54 using pointer = std::add_pointer_t<reference>;
58 std::variant<CompoundTagVariant const*, CompoundTag::const_iterator, ListTag::const_iterator>,
59 std::variant<CompoundTagVariant*, CompoundTag::iterator, ListTag::iterator>>
62 static Iterator makeBegin(
auto& var)
noexcept {
64 switch (var.index()) {
66 res.iter.template emplace<2>(var.template get<ListTag>().begin());
69 res.iter.template emplace<1>(var.template get<CompoundTag>().begin());
72 res.iter.template emplace<0>(std::addressof(var) + 1);
75 res.iter.template emplace<0>(std::addressof(var));
80 static Iterator makeEnd(
auto& var)
noexcept {
82 switch (var.index()) {
84 res.iter.template emplace<2>(var.template get<ListTag>().end());
87 res.iter.template emplace<1>(var.template get<CompoundTag>().end());
90 res.iter.template emplace<0>(std::addressof(var) + 1);
95 [[nodiscard]] reference operator*()
const noexcept {
96 switch (iter.index()) {
98 return std::get<0>(iter)->get();
100 return std::get<1>(iter)->second.get();
102 return *std::get<2>(iter)->get();
109 [[nodiscard]] pointer operator->()
const noexcept {
return std::addressof(**
this); }
112 std::visit([](
auto& val) { ++val; }, iter);
123 std::visit([](
auto& val) { --val; }, iter);
133 [[nodiscard]]
bool operator==(
Iterator const& r)
const noexcept {
return this->iter == r.iter; }
144 LLNDAPI
static ll::Expected<CompoundTagVariant>
147 [[nodiscard]]
constexpr CompoundTagVariant() =
default;
149 [[nodiscard]]
constexpr CompoundTagVariant(CompoundTagVariant&&) =
default;
151 LL_MAY_CONSTEXPR CompoundTagVariant& operator=(CompoundTagVariant&&) =
default;
153 [[nodiscard]]
constexpr CompoundTagVariant(CompoundTagVariant
const&) =
default;
155 LL_MAY_CONSTEXPR CompoundTagVariant& operator=(CompoundTagVariant
const&) =
default;
158 requires(
requires(T o) { mTagStorage = std::move(o); })
160 mTagStorage = std::move(other);
164 [[nodiscard]]
constexpr CompoundTagVariant(std::nullptr_t) {}
166 [[nodiscard]]
bool operator==(CompoundTagVariant
const& other)
const {
return get() == other.get(); }
168 [[nodiscard]] CompoundTagVariant(Variant tag) : mTagStorage(std::move(tag)) {}
170 template <
class T,
class... Args>
171 [[nodiscard]]
constexpr CompoundTagVariant(std::in_place_type_t<T>, Args&&... args)
172 : mTagStorage(std::in_place_type<T>, std::forward<Args>(args)...) {}
174 [[nodiscard]]
constexpr CompoundTagVariant(std::initializer_list<CompoundTag::TagMap::value_type> tagPairs)
175 : mTagStorage(std::in_place_type<CompoundTag>, tagPairs) {}
177 [[nodiscard]] CompoundTagVariant(UniqueTagPtr&& tag) {
181 ::ll::meta::visitIndex<Types::size>(
static_cast<size_t>(tag->getId()), [&]<
size_t I> {
182 mTagStorage = std::move((Types::get<I>&)*tag);
185 [[nodiscard]] CompoundTagVariant(UniqueTagPtr
const& tag) : CompoundTagVariant(tag ? tag->copy() : nullptr) {}
186 template <std::derived_from<Tag> T>
187 [[nodiscard]]
constexpr CompoundTagVariant(T tag) : mTagStorage(std::move(tag)) {}
188 template <std::
integral T>
189 [[nodiscard]]
constexpr CompoundTagVariant(T integer) {
190 constexpr size_t size =
sizeof(T);
191 if constexpr (size == 1) {
192 mTagStorage = ByteTag{integer};
193 }
else if constexpr (size == 2) {
194 mTagStorage = ShortTag{integer};
195 }
else if constexpr (size == 4) {
196 mTagStorage = IntTag{integer};
198 mTagStorage = Int64Tag{integer};
201 [[nodiscard]]
constexpr CompoundTagVariant(std::byte b) : mTagStorage(ByteTag{b}) {}
203 [[nodiscard]]
constexpr CompoundTagVariant(
float f) : mTagStorage(FloatTag{f}) {}
205 [[nodiscard]]
constexpr CompoundTagVariant(
double d) : mTagStorage(DoubleTag{d}) {}
207 [[nodiscard]]
constexpr CompoundTagVariant(std::string s)
208 : mTagStorage(std::in_place_type<StringTag>, std::move(s)) {}
210 [[nodiscard]]
constexpr CompoundTagVariant(std::string_view s) : mTagStorage(std::in_place_type<StringTag>, s) {}
213 [[nodiscard]]
constexpr CompoundTagVariant(
char const (&str)[N])
214 : CompoundTagVariant(std::string_view{str, N - 1}) {}
216 [[nodiscard]] iterator begin() noexcept {
return iterator::makeBegin(*
this); }
217 [[nodiscard]] const_iterator begin() const noexcept {
return cbegin(); }
218 [[nodiscard]] const_iterator cbegin() const noexcept {
return const_iterator::makeBegin(*
this); }
220 [[nodiscard]] iterator end() noexcept {
return iterator::makeEnd(*
this); }
221 [[nodiscard]] const_iterator end() const noexcept {
return cend(); }
222 [[nodiscard]] const_iterator cend() const noexcept {
return const_iterator::makeEnd(*
this); }
224 [[nodiscard]]
constexpr Tag::Type index() const noexcept {
return Tag::Type(mTagStorage.index()); }
225 [[nodiscard]]
constexpr Tag::Type getId() const noexcept {
return index(); }
227 template <std::derived_from<Tag> T>
228 [[nodiscard]]
constexpr bool hold() const noexcept {
229 return std::holds_alternative<T>(mTagStorage);
231 [[nodiscard]]
constexpr bool hold(::Tag::Type type)
const noexcept {
return getId() == type; }
234 [[nodiscard]]
constexpr bool is_array() const noexcept {
return hold(Tag::List); }
235 [[nodiscard]]
constexpr bool is_binary() const noexcept {
return hold(Tag::ByteArray) || hold(Tag::IntArray); }
236 [[nodiscard]]
constexpr bool is_boolean() const noexcept {
return hold(Tag::Byte); }
237 [[nodiscard]]
constexpr bool is_null() const noexcept {
return hold(Tag::End); }
238 [[nodiscard]]
constexpr bool is_number_float() const noexcept {
return hold(Tag::Float) || hold(Tag::Double); }
239 [[nodiscard]]
constexpr bool is_number_integer() const noexcept {
240 return hold(Tag::Byte) || hold(Tag::Short) || hold(Tag::Int) || hold(Tag::Int64);
242 [[nodiscard]]
constexpr bool is_object() const noexcept {
return hold(Tag::Compound); }
243 [[nodiscard]]
constexpr bool is_string() const noexcept {
return hold(Tag::String); }
244 [[nodiscard]]
constexpr bool is_number() const noexcept {
return is_number_float() || is_number_integer(); }
245 [[nodiscard]]
constexpr bool is_primitive() const noexcept {
246 return is_null() || is_string() || is_number() || is_binary();
248 [[nodiscard]]
constexpr bool is_structured() const noexcept {
return is_array() || is_object(); }
250 [[nodiscard]]
constexpr CompoundTag::TagMap
const& items()
const {
return get<CompoundTag>().mTags; }
251 [[nodiscard]]
constexpr CompoundTag::TagMap& items() {
return get<CompoundTag>().mTags; }
253 [[nodiscard]]
bool contains(std::string_view key)
const noexcept {
255 return get<CompoundTag>().contains(key);
260 [[nodiscard]]
bool contains(std::string_view key, Tag::Type type)
const noexcept {
262 return get<CompoundTag>().contains(key, type);
267 template <std::derived_from<Tag> T>
268 [[nodiscard]]
bool contains(std::string_view key)
const noexcept {
269 constexpr size_t idx = Types::index<T>;
270 return contains(key, (Tag::Type)idx);
273 [[nodiscard]]
constexpr size_t size() const noexcept {
284 return get<ListTag>().size();
286 return get<CompoundTag>().size();
288 return get<IntArrayTag>().size();
290 return get<ByteArrayTag>().size();
298 template <std::derived_from<Tag> T>
299 [[nodiscard]]
constexpr T& get() {
300 return std::get<T>(mTagStorage);
303 template <std::derived_from<Tag> T>
304 [[nodiscard]]
constexpr T
const& get()
const {
305 return std::get<T>(mTagStorage);
308 [[nodiscard]] Tag& get() {
return reinterpret_cast<Tag&
>(mTagStorage); }
310 [[nodiscard]] Tag
const& get()
const {
return reinterpret_cast<Tag const&
>(mTagStorage); }
312 template <std::derived_from<Tag> T>
313 constexpr T& emplace() {
314 return mTagStorage.emplace<T>();
317 [[nodiscard]] UniqueTagPtr& operator[](
size_t index) {
318 if (hold(Tag::List)) {
319 return get<ListTag>()[index];
321 throw std::runtime_error(
"tag not hold an array");
325 [[nodiscard]] UniqueTagPtr
const& operator[](
size_t index)
const {
326 if (hold(Tag::List)) {
327 return get<ListTag>()[index];
329 throw std::runtime_error(
"tag not hold an array");
333 [[nodiscard]] CompoundTagVariant& operator[](std::string_view index) {
335 mTagStorage = CompoundTag{};
337 if (!hold(Tag::Compound)) {
338 throw std::runtime_error(
"tag not hold an object");
340 return get<CompoundTag>()[index];
343 [[nodiscard]] CompoundTagVariant
const& operator[](std::string_view index)
const {
344 if (!hold(Tag::Compound)) {
345 throw std::runtime_error(
"tag not hold an object");
347 return get<CompoundTag>()[index];
351 [[nodiscard]] CompoundTagVariant& operator[](
char const (&index)[N]) {
352 return operator[](std::string_view{index, N - 1});
356 [[nodiscard]] CompoundTagVariant
const& operator[](
char const (&index)[N])
const {
357 return operator[](std::string_view{index, N - 1});
360 [[nodiscard]] UniqueTagPtr toUniqueCopy() const& {
362 [](
auto& val) -> std::unique_ptr<Tag> {
return std::make_unique<std::decay_t<
decltype(val)>>(val); },
367 [[nodiscard]] UniqueTagPtr toUnique() && {
369 [](
auto&& val) -> std::unique_ptr<Tag> {
370 return std::make_unique<std::decay_t<
decltype(val)>>(std::move(val));
376 LLNDAPI std::string toSnbt(SnbtFormat snbtFormat = SnbtFormat::PrettyFilePrint, uchar indent = 4) const noexcept;
378 std::
string dump(uchar indent = 4, SnbtFormat snbtFormat = SnbtFormat::PrettyFilePrint) const noexcept {
379 return toSnbt(snbtFormat, indent);
382 void push_back(CompoundTagVariant val) {
384 mTagStorage = ListTag{};
386 if (!hold(Tag::List)) {
387 throw std::runtime_error(
"tag not hold an array");
389 get<ListTag>().add(std::move(val).toUnique());
393 requires(std::is_arithmetic_v<T> && !ll::traits::is_char_v<T>)
394 [[nodiscard]]
constexpr operator T()
const {
398 if constexpr (std::is_convertible_v<std::decay_t<
decltype(val)>, T>) {
407 throw std::runtime_error(
"tag not hold an number");
410 [[nodiscard]]
operator std::string
const&()
const {
return get<StringTag>(); }
411 [[nodiscard]]
operator std::string&() {
return get<StringTag>(); }
412 [[nodiscard]]
operator std::string&&() && {
return std::move(get<StringTag>()); }
413 [[nodiscard]]
operator std::string_view()
const {
return get<StringTag>(); }
414 static CompoundTagVariant object(std::initializer_list<CompoundTag::TagMap::value_type> init = {}) {
415 return CompoundTagVariant{std::in_place_type<CompoundTag>, init};
417 static CompoundTagVariant array(std::initializer_list<CompoundTagVariant> init = {}) {
418 return CompoundTagVariant{std::in_place_type<ListTag>, init};