#pragma once #include "packbits-impl.hpp" #include "compat/reverse-index-sequence.hpp" #include #include #include #include namespace floormat::Pack_impl { template struct output { static_assert(std::is_fundamental_v); static_assert(LEFT >= 0); static_assert(LEFT <= CAPACITY); static_assert(CAPACITY <= sizeof(T)*8); static constexpr size_t Capacity = CAPACITY, Left = LEFT; T value{0}; }; template struct output_field { static_assert(LENGTH > 0); static_assert(LENGTH <= sizeof(T)*8); static constexpr size_t Length = LENGTH; T value; }; template struct is_output_field : std::bool_constant {}; template struct is_output_field> : std::bool_constant { static_assert(N > 0); }; template constexpr CORRADE_ALWAYS_INLINE T write_(const Tuple& tuple, output st, std::index_sequence) { static_assert(Capacity > 0); static_assert(Capacity <= sizeof(T)*8); static_assert(Left > 0, "too many bits to write"); static_assert(Left <= Capacity, "too many bits to write"); static_assert(I < std::tuple_size_v, "too few tuple elements"); static_assert(is_output_field(tuple))>>{}, "tuple element must be output"); constexpr size_t N = std::tuple_element_t::Length; static_assert(N <= Left, "too many bits to write"); T x = std::get(tuple).value; if (!((size_t)std::bit_width(x) <= N)) [[unlikely]] throw_on_write_input_bit_overflow(); T value = T(T(st.value << N) | x); return write_(tuple, output{value}, std::index_sequence{}); } template constexpr CORRADE_ALWAYS_INLINE T write_(const Tuple&, output st, std::index_sequence<>) { return st.value; } } // namespace floormat::Pack_impl namespace floormat { template [[nodiscard]] constexpr T pack_write(const std::tuple...>& tuple) { constexpr size_t nbits = sizeof(T)*8; return Pack_impl::write_(tuple, Pack_impl::output{T{0}}, make_reverse_index_sequence{}); } constexpr uint8_t pack_write(const std::tuple<>&) = delete; } // namespace floormat