in include/ylt/struct_pack/calculate_size.hpp [40:183]
constexpr size_info inline calculate_one_size(const T &item) {
constexpr auto id = get_type_id<remove_cvref_t<T>, parent_tag>();
static_assert(id != detail::type_id::type_end_flag);
using type = remove_cvref_t<decltype(item)>;
static_assert(!std::is_pointer_v<type>);
size_info ret{};
if constexpr (id == type_id::monostate_t) {
}
else if constexpr (id == type_id::user_defined_type) {
ret.total = sp_get_needed_size(item);
}
else if constexpr (detail::varint_t<type, parent_tag>) {
if constexpr (is_enable_fast_varint_coding(parent_tag)) {
// skip it. It has been calculated in parent.
}
else {
ret.total = detail::calculate_varint_size(item);
}
}
else if constexpr (std::is_fundamental_v<type> || std::is_enum_v<type> ||
id == type_id::int128_t || id == type_id::uint128_t ||
id == type_id::bitset_t) {
ret.total = sizeof(type);
}
else if constexpr (is_trivial_view_v<type>) {
return calculate_one_size(item.get());
}
else if constexpr (id == type_id::array_t) {
if constexpr (is_trivial_serializable<type>::value) {
ret.total = sizeof(type);
}
else {
for (auto &i : item) {
ret += calculate_one_size(i);
}
}
}
else if constexpr (container<type>) {
ret.size_cnt += 1;
ret.max_size = item.size();
if constexpr (trivially_copyable_container<type>) {
using value_type = typename type::value_type;
ret.total = item.size() * sizeof(value_type);
}
else {
for (auto &&i : item) {
ret += calculate_one_size(i);
}
}
}
else if constexpr (container_adapter<type>) {
static_assert(!sizeof(type), "the container adapter type is not supported");
}
else if constexpr (!pair<type> && tuple<type> && !is_trivial_tuple<type>) {
std::apply(
[&](auto &&...items) CONSTEXPR_INLINE_LAMBDA {
ret += calculate_payload_size(items...);
},
item);
}
else if constexpr (ylt::reflection::optional<type>) {
ret.total = sizeof(char);
if (item) {
ret += calculate_one_size(*item);
}
}
else if constexpr (unique_ptr<type>) {
ret.total = sizeof(char);
if (item) {
if constexpr (is_base_class<typename type::element_type>) {
ret.total += sizeof(uint32_t);
bool is_ok = false;
auto index = search_type_by_md5<typename type::element_type>(
item->get_struct_pack_id(), is_ok);
if SP_UNLIKELY (!is_ok) {
throw std::runtime_error{
"illegal struct_pack_id in virtual function."};
}
ret += ylt::reflection::template_switch<
calculate_one_size_derived_class_helper<
derived_class_set_t<typename type::element_type>>>(index,
item.get());
}
else {
ret += calculate_one_size(*item);
}
}
}
else if constexpr (is_variant_v<type>) {
ret.total = sizeof(uint8_t);
ret += std::visit(
[](const auto &e) {
return calculate_one_size(e);
},
item);
}
else if constexpr (ylt::reflection::expected<type>) {
ret.total = sizeof(bool);
if (item.has_value()) {
if constexpr (!std::is_same_v<typename type::value_type, void>)
ret += calculate_one_size(item.value());
}
else {
ret += calculate_one_size(item.error());
}
}
else if constexpr (std::is_class_v<type>) {
if constexpr (!pair<type> && !is_trivial_tuple<type>) {
if constexpr (!user_defined_refl<type>)
static_assert(std::is_aggregate_v<remove_cvref_t<type>>,
"struct_pack only support aggregated type, or you should "
"add macro YLT_REFL(Type,field1,field2...)");
}
if constexpr (is_trivial_serializable<type>::value) {
ret.total = sizeof(type);
}
else if constexpr (is_trivial_serializable<type, true>::value) {
visit_members(item, [&](auto &&...items) CONSTEXPR_INLINE_LAMBDA {
ret += calculate_payload_size(items...);
ret.total += align::total_padding_size<type>;
});
}
else {
constexpr uint64_t tag = get_parent_tag<type>();
if constexpr (is_enable_fast_varint_coding(tag)) {
ret.total +=
visit_members(item, [](auto &&...items) CONSTEXPR_INLINE_LAMBDA {
constexpr uint64_t tag =
get_parent_tag<type>(); // to pass msvc with c++17
return calculate_fast_varint_size<tag>(items...);
});
}
ret += visit_members(item, [](auto &&...items) CONSTEXPR_INLINE_LAMBDA {
constexpr uint64_t tag =
get_parent_tag<type>(); // to pass msvc with c++17
return calculate_payload_size<tag>(items...);
});
}
}
else {
static_assert(!sizeof(type), "the type is not supported yet");
}
return ret;
}