#pragma once #include #include #include #include "common/types.h" namespace rst::util { namespace detail { #if defined(RST_VER) constexpr u32 Version = RST_VER; #else constexpr u32 Version = 0; #endif static_assert(Version == 0 || Version == 1, "Unknown version"); template * = nullptr> constexpr uintptr_t GetAddr(Ts... addresses) { return std::get(std::forward_as_tuple(addresses...)); } template constexpr uintptr_t GetAddr(Ts...) { return 0; } } // namespace detail /// Returns a version-specific address from a list of addresses and casts it to Type*. template constexpr auto GetPointer(Ts... addresses) { static_assert(detail::Version < sizeof...(Ts), "Missing address!"); return reinterpret_cast(detail::GetAddr(addresses...)); } /// Returns the offset in bytes of a member. /// Unlike offsetof, this works for derived classes as well. template inline size_t constexpr OffsetOf(T1 T2::*member) { constexpr T2 object{}; return size_t(&(object.*member)) - size_t(&object); } template Dest BitCastPtr(const T* ptr, size_t offset = 0) { Dest dest; std::memcpy(&dest, reinterpret_cast(ptr) + offset, sizeof(dest)); return dest; } } // namespace rst::util