Botcraft 1.21.4
Loading...
Searching...
No Matches
Templates.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <bitset>
5#include <map>
6#include <memory>
7#include <optional>
8#include <tuple>
9#include <utility>
10#include <vector>
11
12namespace ProtocolCraft
13{
14 namespace NBT
15 {
16 class Value;
17 class UnnamedValue;
18 }
19
20 namespace Json
21 {
22 class Value;
23 }
24
25 template <typename T>
26 struct VarType { using underlying_type = T; };
27
28
29 namespace Internal
30 {
31 /// @brief Default case, see field_index specialization for implementation details
32 template <size_t N, typename T, template <size_t, typename> typename U, typename = void>
33 static constexpr size_t field_index = 0;
34
35 /// @brief A templated size_t that counts the number of existing classes U with a "field_name" member
36 /// @tparam N Current counter for recursion (user should always call it with 0)
37 /// @tparam T Can be any type, must be different for each field we want to be counted later (used because we can't have a empty template<> specialization nested in a class)
38 /// @tparam U The templated class that will be searched for match
39 template <size_t N, typename T, template <size_t, typename> typename U>
40 static constexpr size_t field_index<N, T, U, std::void_t<decltype(U<N, T>::field_name)>> = 1 + field_index<N + 1, T, U>;
41
42 /// @brief Concat multiple tuples in one big tuple
43 /// @tparam ...input_t Multiple std::tuple types to concat
44 template<typename ... input_t>
46 decltype(std::tuple_cat(
47 std::declval<input_t>()...
48 ));
49
50 template <typename T, typename Tuple> constexpr bool tuple_contains_type = false;
51 template <typename T, typename... Ts> constexpr bool tuple_contains_type<T, std::tuple<Ts...>> = std::disjunction_v<std::is_same<T, Ts>...>;
52
53 template <typename T, typename Tuple> constexpr int get_tuple_index = 0;
54 template <typename T, typename... Rest> constexpr int get_tuple_index<T, std::tuple<T, Rest...>> = 0;
55 template <typename T, typename First, typename... Rest> constexpr int get_tuple_index<T, std::tuple<First, Rest...>> = 1 + get_tuple_index<T, std::tuple<Rest...>>;
56
57 // Template black magic to loop at compile time
58 template<std::size_t... indices, class LoopBody>
59 void loop_impl(std::index_sequence<indices...>, LoopBody&& loop_body) {
60 (loop_body(std::integral_constant<std::size_t, indices>{}), ...);
61 }
62
63 template<std::size_t N, class LoopBody>
64 void loop(LoopBody&& loop_body) {
65 loop_impl(std::make_index_sequence<N>{}, std::forward<LoopBody>(loop_body));
66 }
67
68
69 /// @brief Just a simple type wrapper that will store with T1 and serialize as T2 (can be used for Enum/VarInt for example)
70 /// @tparam T1 Storage type
71 /// @tparam T2 Serialization type
72 template <typename T1, typename T2> struct DiffType {};
73
74 template <typename T> struct GetClassFromConditionPtr;
75 template <typename C> struct GetClassFromConditionPtr<bool(C::*)() const> { using Class = C; };
76
77 /// @brief A type wrapper to conditionally serialize a type
78 /// @tparam T Underlying type, can be VarType or DiffType too
79 /// @tparam Condition A condition function pointer to a non static const class member function returning a bool, i.e. ``bool(*Class::Condition)(const Class*) const``
80 /// @tparam StoredAsOptional If true, T will be stored as empty std::optional when Condition is not satisfied instead of default initialized values
81 template <typename T, auto Condition, bool StoredAsOptional = true>
83 {
84 using type = T;
85 static constexpr bool stored_as_optional = StoredAsOptional;
86 // Technically we could just store Condition and use it with (this->*Conditioned::Condition)() but that's a bit ugly
87 // So instead we use this simpler tu use wrapper around it
88 static bool Evaluate(const typename GetClassFromConditionPtr<decltype(Condition)>::Class* t)
89 {
90 return (t->*Condition)();
91 }
92 };
93
94 template <typename T, typename S = VarType<int>, size_t N = 0>
95 struct Vector
96 {
97 using value_type = T;
98 using size_type = S;
99 static constexpr size_t size = N;
100 static_assert(std::is_same_v<S, void> || N == 0, "Can't specify a size type if N > 0");
101 };
102
103 template <typename T> struct SerializedType;
104
105 template <typename T, auto ReadFunc, auto WriteFunc, auto SerializeFunc>
106 struct CustomType;
107
108 template <typename T> constexpr bool IsArray = false;
109 template <typename T, size_t N> constexpr bool IsArray<std::array<T, N>> = true;
110 template <typename T> constexpr bool IsVector = false;
111 template <typename T> constexpr bool IsVector<std::vector<T>> = true;
112 template <typename T> constexpr bool IsGenericVector = false;
113 template <typename T, typename U, size_t N> constexpr bool IsGenericVector<Vector<T, U, N>> = true;
114 template <typename T> constexpr bool IsMap = false;
115 template <typename K, typename V> constexpr bool IsMap<std::map<K, V>> = true;
116 template <typename T> constexpr bool IsVarType = false;
117 template <typename T> constexpr bool IsVarType<VarType<T>> = true;
118 template <typename T> constexpr bool IsOptional = false;
119 template <typename T> constexpr bool IsOptional<std::optional<T>> = true;
120 template <typename T> constexpr bool IsPair = false;
121 template <typename T1, typename T2> constexpr bool IsPair<std::pair<T1, T2>> = true;
122 template <typename T> constexpr bool IsBitset = false;
123 template <size_t N> constexpr bool IsBitset<std::bitset<N>> = true;
124 template <typename T> constexpr bool IsConditioned = false;
125 template <typename T, auto C, bool b> constexpr bool IsConditioned<Conditioned<T, C, b>> = true;
126 template <typename T> constexpr bool IsCustomType = false;
127 template <typename T, auto R, auto W, auto S> constexpr bool IsCustomType<CustomType<T, R, W, S>> = true;
128 template <typename T> constexpr bool IsSharedPtr = false;
129 template <typename T> constexpr bool IsSharedPtr<std::shared_ptr<T>> = true;
130
131
132 template <typename T> struct SerializedType { using storage_type = T; using serialization_type = T; };
133 template <typename T> struct SerializedType<VarType<T>> { using storage_type = T; using serialization_type = VarType<T>; };
134 template <> struct SerializedType<NBT::UnnamedValue> { using storage_type = NBT::Value; using serialization_type = NBT::UnnamedValue; };
135 template <typename T, size_t N> struct SerializedType<std::array<T, N>> { using storage_type = std::array<typename SerializedType<T>::storage_type, N>; using serialization_type = std::array<T, N>; };
136 template <typename T> struct SerializedType<std::vector<T>> { using storage_type = std::vector<typename SerializedType<T>::storage_type>; using serialization_type = std::vector<T>; };
137 template <typename T> struct SerializedType<Vector<T, void, 0>> { using storage_type = std::vector<typename SerializedType<T>::storage_type>; using serialization_type = Vector<T, void, 0>; };
138 template <typename T, size_t N> struct SerializedType<Vector<T, void, N>> { using storage_type = std::array<typename SerializedType<T>::storage_type, N>; using serialization_type = Vector<T, void, N>; };
139 template <typename T, typename U> struct SerializedType<Vector<T, U>> { using storage_type = std::vector<typename SerializedType<T>::storage_type>; using serialization_type = Vector<T, U>; };
140 template <typename T> struct SerializedType<std::optional<T>> { using storage_type = std::optional<typename SerializedType<T>::storage_type>; using serialization_type = std::optional<T>; };
141 template <typename K, typename V> struct SerializedType<std::map<K, V>> { using storage_type = std::map<typename SerializedType<K>::storage_type, typename SerializedType<V>::storage_type>; using serialization_type = std::map<K, V>; };
142 template <typename T1, typename T2> struct SerializedType<std::pair<T1, T2>> { using storage_type = std::pair<typename SerializedType<T1>::storage_type, typename SerializedType<T2>::storage_type>; using serialization_type = std::pair<T1, T2>; };
143 template <typename T1, typename T2> struct SerializedType<DiffType<T1, T2>> { using storage_type = T1; using serialization_type = T2; };
144 template <typename T, auto F> struct SerializedType<Conditioned<T, F, true>> { using storage_type = std::optional<typename SerializedType<T>::storage_type>; using serialization_type = T; };
145 template <typename T, auto F> struct SerializedType<Conditioned<T, F, false>> { using storage_type = typename SerializedType<T>::storage_type; using serialization_type = T; };
146 template <typename T, auto R, auto W, auto S> struct SerializedType<CustomType<T, R, W, S>> { using storage_type = typename SerializedType<T>::storage_type; using serialization_type = T; };
147
148 /// @brief To be used in constexpr else to fail compilation in a C++ compliant way
149 /// @tparam T Any type
150 template <typename T> constexpr bool dependant_false = false;
151
152#ifdef PROTOCOLCRAFT_DETAILED_PARSING
153 template <typename T> struct OffsetType { using type = size_t; };
154 template <typename T> struct OffsetType<std::optional<T>> { using type = typename OffsetType<T>::type; };
155 template <typename T> struct OffsetType<std::vector<T>> { using type = std::pair<size_t, std::vector<typename OffsetType<T>::type>>; };
156 template <typename T, size_t N> struct OffsetType<std::array<T, N>> { using type = std::pair<size_t, std::array<typename OffsetType<T>::type, N>>; };
157 template <typename T1, typename T2> struct OffsetType<std::pair<T1, T2>> { using type = std::pair<size_t, std::pair<typename OffsetType<T1>::type, typename OffsetType<T2>::type>>; };
158 template <typename K, typename V> struct OffsetType<std::map<K, V>> { using type = std::pair<size_t, std::map<K, typename OffsetType<V>::type>>; };
159#endif
160 }
161}
constexpr bool IsVarType
constexpr bool IsArray
constexpr bool IsVector
constexpr bool IsConditioned
static constexpr size_t field_index
Default case, see field_index specialization for implementation details.
Definition Templates.hpp:33
constexpr bool IsCustomType
constexpr bool tuple_contains_type
Definition Templates.hpp:50
constexpr bool IsBitset
constexpr bool IsSharedPtr
void loop_impl(std::index_sequence< indices... >, LoopBody &&loop_body)
Definition Templates.hpp:59
constexpr int get_tuple_index
Definition Templates.hpp:53
constexpr bool IsPair
constexpr bool IsOptional
void loop(LoopBody &&loop_body)
Definition Templates.hpp:64
constexpr bool dependant_false
To be used in constexpr else to fail compilation in a C++ compliant way.
constexpr bool IsGenericVector
decltype(std::tuple_cat(std::declval< input_t >()...)) tuple_cat_t
Concat multiple tuples in one big tuple.
Definition Templates.hpp:48
STL namespace.
A type wrapper to conditionally serialize a type.
Definition Templates.hpp:83
static bool Evaluate(const typename GetClassFromConditionPtr< decltype(Condition)>::Class *t)
Definition Templates.hpp:88
static constexpr bool stored_as_optional
Definition Templates.hpp:85
Just a simple type wrapper that will store with T1 and serialize as T2 (can be used for Enum/VarInt f...
Definition Templates.hpp:72
std::optional< typename SerializedType< T >::storage_type > storage_type
typename SerializedType< T >::storage_type storage_type
std::vector< typename SerializedType< T >::storage_type > storage_type
std::vector< typename SerializedType< T >::storage_type > storage_type
std::array< typename SerializedType< T >::storage_type, N > storage_type
std::array< typename SerializedType< T >::storage_type, N > storage_type
std::map< typename SerializedType< K >::storage_type, typename SerializedType< V >::storage_type > storage_type
std::optional< typename SerializedType< T >::storage_type > storage_type
std::pair< typename SerializedType< T1 >::storage_type, typename SerializedType< T2 >::storage_type > storage_type
std::vector< typename SerializedType< T >::storage_type > storage_type
static constexpr size_t size
Definition Templates.hpp:99