Botcraft 1.21.4
Loading...
Searching...
No Matches
AutoSerializedToJson.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include <utility>
8
9namespace ProtocolCraft
10{
11#ifdef PROTOCOLCRAFT_DETAILED_PARSING
12 inline std::optional<Json::Value> WrapJsonWithOffsets(const std::optional<Json::Value>& v, const size_t* start_offset, const size_t* end_offset)
13 {
14 if (!v.has_value() || start_offset == nullptr || end_offset == nullptr)
15 {
16 return v;
17 }
18
19 return Json::Object({
20 { "start_offset", *start_offset },
21 { "end_offset", *end_offset },
22 { "content", v.value() }
23 });
24 }
25#endif
26
27 template<typename T>
28 std::optional<Json::Value> SerializeType(std::conditional_t<std::is_arithmetic_v<T> || std::is_enum_v<T>, T, const T&> val
29#ifdef PROTOCOLCRAFT_DETAILED_PARSING
30 ,
31 const typename Internal::OffsetType<T>::type* start_offset = nullptr,
32 const typename Internal::OffsetType<T>::type* end_offset = nullptr
33#endif
34 )
35 {
36 if constexpr (Internal::IsOptional<T>)
37 {
38 if (val.has_value())
39 {
40 return SerializeType<typename T::value_type>(val.value()
41#ifdef PROTOCOLCRAFT_DETAILED_PARSING
42 ,
43 start_offset,
44 end_offset
45#endif
46 );
47 }
48 else
49 {
50 return std::nullopt;
51 }
52 }
53 else if constexpr (Internal::IsMap<T>)
54 {
55 Json::Object map_object;
56 for (const auto& [k, v] : val)
57 {
58 const std::optional<Json::Value> serialized = SerializeType<typename T::mapped_type>(v
59#ifdef PROTOCOLCRAFT_DETAILED_PARSING
60 ,
61 (start_offset != nullptr && start_offset->second.find(k) != start_offset->second.end()) ? &start_offset->second.at(k) : nullptr,
62 (end_offset != nullptr && end_offset->second.find(k) != end_offset->second.end()) ? &end_offset->second.at(k) : nullptr
63#endif
64 );
65 if constexpr (std::is_enum_v<typename T::key_type>)
66 {
67 map_object[std::to_string(static_cast<std::underlying_type_t<typename T::key_type>>(k))] = serialized.value_or(Json::Value());
68 }
69 else if constexpr (std::is_integral_v<typename T::key_type> && !std::is_same_v<typename T::key_type, bool>)
70 {
71 map_object[std::to_string(k)] = serialized.value_or(Json::Value());
72 }
73 else if constexpr (std::is_same_v<typename T::key_type, std::string>)
74 {
75 map_object[k] = serialized.value_or(Json::Value());
76 }
77 else if constexpr (std::is_same_v<typename T::key_type, Identifier>)
78 {
79 map_object[k.GetFull()] = serialized.value_or(Json::Value());
80 }
81 else
82 {
83 static_assert(Internal::dependant_false<T>, "Map key type not supported in auto JSON serialization");
84 }
85 }
86
87#ifdef PROTOCOLCRAFT_DETAILED_PARSING
88 return WrapJsonWithOffsets(map_object, start_offset != nullptr ? &start_offset->first : nullptr, end_offset != nullptr ? &end_offset->first : nullptr);
89#else
90 return map_object;
91#endif
92 }
93 else if constexpr (Internal::IsVector<T> || Internal::IsArray<T>)
94 {
95 if constexpr (std::is_same_v<typename T::value_type, char>)
96 {
97 if (val.size() > 16)
98 {
99#ifdef PROTOCOLCRAFT_DETAILED_PARSING
100 return WrapJsonWithOffsets("Vector of " + std::to_string(val.size()) + " chars", start_offset != nullptr ? &start_offset->first : nullptr, end_offset != nullptr ? &end_offset->first : nullptr);
101#else
102 return "Vector of " + std::to_string(val.size()) + " chars";
103
104#endif
105 }
106 else
107 {
108#ifdef PROTOCOLCRAFT_DETAILED_PARSING
109 return WrapJsonWithOffsets(val, start_offset != nullptr ? &start_offset->first : nullptr, end_offset != nullptr ? &end_offset->first : nullptr);
110#else
111 return val;
112#endif
113 }
114 }
115 else if constexpr (std::is_same_v<typename T::value_type, unsigned char>)
116 {
117 if (val.size() > 16)
118 {
119#ifdef PROTOCOLCRAFT_DETAILED_PARSING
120 return WrapJsonWithOffsets("Vector of " + std::to_string(val.size()) + " unsigned chars", start_offset != nullptr ? &start_offset->first : nullptr, end_offset != nullptr ? &end_offset->first : nullptr);
121#else
122 return "Vector of " + std::to_string(val.size()) + " unsigned chars";
123#endif
124 }
125 else
126 {
127#ifdef PROTOCOLCRAFT_DETAILED_PARSING
128 return WrapJsonWithOffsets(val, start_offset != nullptr ? &start_offset->first : nullptr, end_offset != nullptr ? &end_offset->first : nullptr);
129#else
130 return val;
131#endif
132 }
133 }
134 else
135 {
136 Json::Array output;
137 output.reserve(val.size());
138 for (size_t i = 0; i < val.size(); ++i)
139 {
140 output.push_back(SerializeType<typename T::value_type>(val[i]
141#ifdef PROTOCOLCRAFT_DETAILED_PARSING
142 ,
143 (start_offset != nullptr && start_offset->second.size() > i) ? &start_offset->second[i] : nullptr,
144 (end_offset != nullptr && end_offset->second.size() > i) ? &end_offset->second[i] : nullptr
145#endif
146 ).value_or(Json::Value()));
147 }
148#ifdef PROTOCOLCRAFT_DETAILED_PARSING
149 return WrapJsonWithOffsets(output, start_offset != nullptr ? &start_offset->first : nullptr, end_offset != nullptr ? &end_offset->first : nullptr);
150#else
151 return output;
152#endif
153 }
154 }
155 else if constexpr (Internal::IsBitset<T>)
156 {
157#ifdef PROTOCOLCRAFT_DETAILED_PARSING
158 return WrapJsonWithOffsets(val.to_string(), start_offset, end_offset);
159#else
160 return val.to_string();
161#endif
162 }
163 else if constexpr (Internal::IsPair<T>)
164 {
165#ifdef PROTOCOLCRAFT_DETAILED_PARSING
166 return WrapJsonWithOffsets(Json::Value({
167 { "first", WrapJsonWithOffsets(val.first, start_offset != nullptr ? &start_offset->second.first : nullptr, end_offset != nullptr ? &end_offset->second.first : nullptr).value_or(Json::Value()) },
168 { "second", WrapJsonWithOffsets(val.second, start_offset != nullptr ? &start_offset->second.second : nullptr, end_offset != nullptr ? &end_offset->second.second : nullptr).value_or(Json::Value()) }
169 }), start_offset != nullptr ? &start_offset->first : nullptr, end_offset != nullptr ? &end_offset->first : nullptr);
170#else
171 return Json::Value({
172 { "first", val.first },
173 { "second", val.second }
174 });
175#endif
176 }
177 else if constexpr (Internal::IsSharedPtr<T>)
178 {
179 if (val == nullptr)
180 {
181 return std::nullopt;
182 }
183 return SerializeType<typename T::element_type>(*val
184#ifdef PROTOCOLCRAFT_DETAILED_PARSING
185 ,
186 start_offset,
187 end_offset
188#endif
189 );
190 }
191 else
192 {
193#ifdef PROTOCOLCRAFT_DETAILED_PARSING
194 return WrapJsonWithOffsets(val, start_offset, end_offset);
195#else
196 return val;
197#endif
198 }
199 }
200}
Real class declaration, just a derived class of std::vector<Value>
Definition Json.hpp:180
Real class declaration, just a derived class of std::map<std::string, Value>
Definition Json.hpp:186
Main class, basically a JsonVariant with extra utility functions it doesn't inherit JsonVariant direc...
Definition Json.hpp:45
std::optional< Json::Value > SerializeType(std::conditional_t< std::is_arithmetic_v< T >||std::is_enum_v< T >, T, const T & > val)