proxy_helper.hpp (11203B)
1 #ifndef GUARD_POLITESOME_AUSTRALIAN_GLYCOLYLNEURAMINATE_SPITS_FEATHERS_4769 2 #define GUARD_POLITESOME_AUSTRALIAN_GLYCOLYLNEURAMINATE_SPITS_FEATHERS_4769 3 #pragma once 4 5 #include "scraps/uuid.hpp" 6 7 #include <libshit/nonowning_string.hpp> 8 #include <libshit/strong.hpp> 9 10 #include <capnp/common.h> 11 12 #include <boost/preprocessor/cat.hpp> // IWYU pragma: export 13 #include <boost/preprocessor/control/if.hpp> // IWYU pragma: export 14 #include <boost/preprocessor/control/iif.hpp> // IWYU pragma: export 15 #include <boost/preprocessor/seq/for_each.hpp> // IWYU pragma: export 16 #include <boost/preprocessor/tuple/elem.hpp> // IWYU pragma: export 17 18 #include <cstddef> 19 #include <cstdint> 20 #include <type_traits> 21 #include <utility> 22 23 namespace Scraps::Game 24 { 25 class GameState; 26 const char* GetString(const GameState& gs, std::uint32_t pos); 27 28 #define SCRAPS_PROXY_GEN_TYPE_I 0 29 #define SCRAPS_PROXY_GEN_HAS_CAPNP_I 1 30 #define SCRAPS_PROXY_GEN_WRITABLE_I 2 31 #define SCRAPS_PROXY_GEN_NAME_I 3 32 33 #define SCRAPS_PROXY_GEN_CONST_MEMBERS_IMPL2_WR(has_capnp, name) \ 34 BOOST_PP_IIF(has_capnp, while (GetState().Has##name##State()), ) \ 35 return GetState().Get##name##State() 36 37 #define SCRAPS_PROXY_GEN_CONST_MEMBERS_IMPL2(type, has_capnp, writable, name) \ 38 type BOOST_PP_CAT(Get, name)() const \ 39 { \ 40 BOOST_PP_IF(writable, \ 41 SCRAPS_PROXY_GEN_CONST_MEMBERS_IMPL2_WR(has_capnp, name), ); \ 42 BOOST_PP_IIF(has_capnp, return Scraps::Game::ConvertTo<type>( \ 43 GetGameState(), capnp.BOOST_PP_CAT(Get, name)());, ) \ 44 } 45 46 #define SCRAPS_PROXY_GEN_CONST_MEMBERS_IMPL(r, _, tuple) \ 47 SCRAPS_PROXY_GEN_CONST_MEMBERS_IMPL2 tuple 48 49 #define SCRAPS_PROXY_GEN_CONST_MEMBERS(x) \ 50 BOOST_PP_SEQ_FOR_EACH(SCRAPS_PROXY_GEN_CONST_MEMBERS_IMPL, , x) 51 52 namespace Detail 53 { 54 template <typename T> struct GetSetParam2; 55 template <typename Cls, typename Param> 56 struct GetSetParam2<void (Cls::*)(Param)> { using Type = Param; }; 57 template <typename Cls, typename Param> 58 struct GetSetParam2<void (Cls::*)(Param) noexcept> { using Type = Param; }; 59 60 template <auto T> struct GetSetParam1 : GetSetParam2<decltype(T)> {}; 61 template <auto T> using GetSetParam = typename GetSetParam1<T>::Type; 62 } 63 64 #define SCRAPS_PROXY_GEN_MUT_MEMBERS_IMPL_WR0(name) 65 #define SCRAPS_PROXY_GEN_MUT_MEMBERS_IMPL_WR2(name) // do not generate setter 66 67 #define SCRAPS_PROXY_GEN_MUT_MEMBERS_IMPL_WR1(name) \ 68 void BOOST_PP_CAT(Set, name)( \ 69 Detail::GetSetParam<&StateType::BOOST_PP_CAT( \ 70 BOOST_PP_CAT(Set, name), State)> in) \ 71 { \ 72 GetState().BOOST_PP_CAT(BOOST_PP_CAT(Set, name), State) \ 73 (std::move(in)); \ 74 } 75 76 #define SCRAPS_PROXY_GEN_MUT_MEMBERS_IMPL(r, _, tuple) \ 77 BOOST_PP_CAT(SCRAPS_PROXY_GEN_MUT_MEMBERS_IMPL_WR, \ 78 BOOST_PP_TUPLE_ELEM(SCRAPS_PROXY_GEN_WRITABLE_I, tuple))( \ 79 BOOST_PP_TUPLE_ELEM(SCRAPS_PROXY_GEN_NAME_I, tuple)) 80 81 #define SCRAPS_PROXY_GEN_MUT_MEMBERS(x) \ 82 BOOST_PP_SEQ_FOR_EACH(SCRAPS_PROXY_GEN_MUT_MEMBERS_IMPL, , x) 83 84 85 template <typename To, typename From, typename = void> struct ConvertToImpl; 86 template <typename T> struct ConvertToImpl<T, T> 87 { static const T& Convert(const GameState&, const T& t) noexcept { return t; } }; 88 89 template <> struct ConvertToImpl<Libshit::NonowningString, std::uint32_t> 90 { 91 static Libshit::NonowningString Convert(const GameState& gs, std::uint32_t pos) 92 { return GetString(gs, pos); } 93 }; 94 template <> struct ConvertToImpl<const char*, std::uint32_t> 95 { 96 static const char* Convert(const GameState& gs, std::uint32_t pos) 97 { return GetString(gs, pos); } 98 }; 99 100 template <typename T, typename Tag> 101 struct ConvertToImpl<Libshit::StrongTypedef<T, Tag>, T> 102 { 103 using Strong = Libshit::StrongTypedef<T, Tag>; 104 static Strong Convert(const GameState&, T t) { return Strong{t}; } 105 }; 106 107 template <typename To, typename From> 108 struct ConvertToImpl<To, From, std::enable_if_t< 109 std::is_enum_v<To> && !std::is_enum_v<From>>> 110 { static To Convert(const GameState&, From t) { return To{t}; } }; 111 112 template <typename To, typename From> 113 struct ConvertToImpl<To, From, std::enable_if_t< 114 std::is_same_v<typename To::CapnpType::Reader, From>>> 115 { static To Convert(const GameState& gs, From t) { return {t, gs}; } }; 116 117 template <typename To, typename From> 118 inline decltype(auto) ConvertTo(const GameState& gs, From&& from) noexcept 119 { return ConvertToImpl<To, From>::Convert(gs, std::forward<From>(from)); } 120 121 #define SCRAPS_STATE_CTOR(cls, capnp_type) \ 122 using CapnpType = Scraps::Format::Proto::capnp_type; \ 123 cls(typename capnp::List<CapnpType>::Reader lst, \ 124 const GameState& gs, std::uint32_t i) \ 125 : cls{lst[i], gs} {} \ 126 cls(typename CapnpType::Reader var, const GameState& gs) 127 128 #define SCRAPS_STATE_ID_NAME(type) \ 129 SCRAPS_STATE_CTOR(type##State, type) \ 130 : id{var.GetId()}, name{GetString(gs, var.GetName())} {} \ 131 const type##Id id; \ 132 const char* const name 133 134 #define SCRAPS_STATE_ID_NAME_UUID(type) \ 135 SCRAPS_STATE_CTOR(type##State, type) \ 136 : id{var.GetId()}, uuid{var.GetUuid0(), var.GetUuid1()}, \ 137 name{GetString(gs, var.GetName())} {} \ 138 const type##Id id; \ 139 const Uuid uuid; \ 140 const char* const name 141 142 143 #define SCRAPS_STATE_BF_SIMPLE(name, type) \ 144 auto Get##name##State() const noexcept \ 145 { return bf.Get<Bf##name>(); } \ 146 void Set##name##State(type in) \ 147 { bf.Set<Bf##name>(in); } 148 149 #define SCRAPS_STATE_BF_HAS(name) \ 150 bool Has##name##State() const noexcept { return bf.Get<BfHas##name>(); } \ 151 void Clear##name##State() noexcept { bf.Set<BfHas##name>(false); } 152 153 #define SCRAPS_STATE_BF_OPT_SIMPLE(name, var) \ 154 SCRAPS_STATE_BF_HAS(name) \ 155 auto& Get##name##State() noexcept { return var; } \ 156 const auto& Get##name##State() const noexcept { return var; } \ 157 void Set##name##State(decltype(var) in) \ 158 { \ 159 var = Libshit::Move(in); \ 160 bf.Set<BfHas##name>(true); \ 161 } 162 163 #define SCRAPS_STATE_BF_OPT(name, enum_type) \ 164 bool Has##name##State() const noexcept \ 165 { return bf.Get<Bf##name>().has_value(); } \ 166 void Clear##name##State() noexcept { return bf.Set<Bf##name>({}); } \ 167 \ 168 auto Get##name##State() const noexcept { return *bf.Get<Bf##name>(); } \ 169 void Set##name##State(enum_type e) noexcept { bf.Set<Bf##name>(e); } 170 171 #define SCRAPS_STATE_OPT_ID(name, var) \ 172 bool Has##name##State() const noexcept \ 173 { return static_cast<Id>(var) != INVALID_ID; } \ 174 void Clear##name##State() noexcept { var = decltype(var){INVALID_ID}; } \ 175 auto Get##name##State() const noexcept { return var; } \ 176 void Set##name##State(decltype(var) in) { var = in; } 177 178 #define SCRAPS_STATE_OPT(name, var) \ 179 bool Has##name##State() const noexcept { return var.has_value(); } \ 180 void Clear##name##State() noexcept { var = {}; } \ 181 auto& Get##name##State() noexcept { return *var; } \ 182 const auto& Get##name##State() const noexcept { return *var; } \ 183 void Set##name##State(std::decay_t<decltype(*var)> in) { var = in; } 184 185 #define SCRAPS_STATE_SIMPLE(name, var) \ 186 auto& Get##name##State() noexcept { return var; } \ 187 const auto& Get##name##State() const noexcept { return var; } \ 188 void Set##name##State(std::decay_t<decltype(var)> in) { var = in; } 189 190 template <typename Capnp> 191 class ConstNoStateProxyBase 192 { 193 public: 194 using CapnpType = Capnp; 195 196 ConstNoStateProxyBase(std::nullptr_t) {} // don't use if you can 197 198 ConstNoStateProxyBase(typename CapnpType::Reader rd, const GameState& gs) 199 : capnp{rd}, gs{&gs} {} 200 201 const GameState& GetGameState() const noexcept { return *this->gs; } 202 203 protected: 204 typename CapnpType::Reader capnp; 205 const GameState* gs = nullptr; 206 }; 207 208 template <typename State> 209 class ConstProxyBase : public ConstNoStateProxyBase<typename State::CapnpType> 210 { 211 using Base = ConstNoStateProxyBase<typename State::CapnpType>; 212 public: 213 using CapnpType = typename State::CapnpType; 214 using StateType = State; 215 216 ConstProxyBase(std::nullptr_t) : Base{nullptr} {} 217 218 ConstProxyBase( 219 std::uint32_t i, const StateType& state, // state container 220 typename capnp::List<CapnpType>::Reader lst, const GameState& gs) // fwd 221 : Base{lst[i], gs}, state{&state} {} 222 223 ConstProxyBase(typename CapnpType::Reader rd, 224 const StateType& state, const GameState& gs) 225 : Base{rd, gs}, state{&state} {} 226 227 const StateType& GetState() const noexcept { return *this->state; } 228 229 protected: 230 const StateType* state = nullptr; 231 }; 232 233 template <typename State> 234 class ConstProxyBaseIdName : public ConstProxyBase<State> 235 { 236 public: 237 using ConstProxyBase<State>::ConstProxyBase; 238 239 auto GetId() const noexcept { return this->GetState().id; } 240 const char* GetName() const noexcept { return this->GetState().name; } 241 }; 242 243 template <typename State> 244 class ConstProxyBaseIdNameUuid : public ConstProxyBaseIdName<State> 245 { 246 public: 247 using ConstProxyBaseIdName<State>::ConstProxyBaseIdName; 248 Uuid GetUuid() const noexcept { return this->GetState().uuid; } 249 }; 250 251 struct ProxyConstCast {}; 252 253 template <typename Base> 254 class ProxyBase : public Base 255 { 256 public: 257 using ConstProxy = Base; 258 259 ProxyBase(std::nullptr_t) : Base{nullptr} {} 260 261 ProxyBase( 262 std::uint32_t i, typename Base::StateType& state, 263 typename capnp::List<typename Base::CapnpType>::Reader lst, GameState& gs) 264 : Base{lst[i], state, gs} {} 265 266 ProxyBase( 267 typename Base::CapnpType::Reader rd, typename Base::StateType& state, 268 GameState& gs) 269 : Base{rd, state, gs} {} 270 271 ProxyBase(ProxyConstCast, const Base& base) : Base{base} {} 272 273 GameState& GetGameState() const noexcept 274 { return const_cast<GameState&>(*this->gs); } 275 typename Base::StateType& GetState() noexcept 276 { return const_cast<typename Base::StateType&>(*this->state); } 277 }; 278 279 } 280 281 #endif