scraps

Abandon all hope, ye who enter here.
git clone https://git.neptards.moe/neptards/scraps.git
Log | Files | Refs | Submodules | README | LICENSE

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