#pragma once #include #include #include #include #include "compat/assert.hpp" namespace floormat::detail_Pack_input { template struct input_bits final { static_assert(std::is_fundamental_v); static_assert(N > 0); static_assert(N < sizeof(T)*8); using type = T; }; template struct make_tuple_type_ { template using index_to_type = T; template struct aux; template struct aux> { static_assert(sizeof...(Is) > 0); using type = std::tuple...>; }; using Seq = typename aux>::type; }; template using make_tuple_type = typename make_tuple_type_::Seq; template struct empty_pack_tuple {}; template struct input { static_assert(CAPACITY <= sizeof(T)*8); static constexpr size_t Capacity = CAPACITY; T value; template struct next_ { static_assert(N <= Capacity); using type = input; }; template using next = typename next_::type; template constexpr T get() const { static_assert(N > 0); static_assert(N <= sizeof(T)*8); static_assert(N <= Capacity); return T(value & (T{1} << N) - T{1}); } template constexpr T advance() const { static_assert(N <= sizeof(T)*8); static_assert(N <= Capacity); return T(value >> N); } constexpr bool operator==(const input&) const noexcept = default; [[nodiscard]] constexpr inline bool check_zero() const { return value == T{0}; } }; template struct input { using Type = T; static constexpr size_t Capacity = 0; T value; template [[maybe_unused]] constexpr T get() const = delete; template [[maybe_unused]] constexpr T advance() const = delete; constexpr bool operator==(const input&) const noexcept = default; [[nodiscard]] constexpr inline bool check_zero() const { return true; } template struct next { static_assert(N == (size_t)-1, "reading past the end"); static_assert(N != (size_t)-1); }; }; template constexpr void read_(Place& p, input st, std::index_sequence, empty_pack_tuple, Sizes...>) { static_assert(sizeof...(Is) == sizeof...(Sizes)); static_assert(Size <= Left, "data type too small"); static_assert(I < std::tuple_size_v, "too few tuple members"); using S = input; using next_type = typename S::template next; get(p) = st.template get(); T next_value = st.template advance(); read_(p, next_type{ next_value }, std::index_sequence{}, empty_pack_tuple{}); } template constexpr void read_(Place&, input st, std::index_sequence<>, empty_pack_tuple<>) { fm_assert(st.check_zero()); } template requires(sizeof...(Is) != sizeof...(Sizes)) constexpr void read_(Place&, input, std::index_sequence, empty_pack_tuple) = delete; template using make_pack = empty_pack_tuple...>; } // namespace floormat::detail_Pack_input namespace floormat::pack { } // namespace floormat::pack