in include/ylt/standalone/iguana/pb_reader.hpp [27:184]
IGUANA_INLINE void from_pb_impl(T& val, std::string_view& pb_str,
uint32_t field_no) {
size_t pos = 0;
if constexpr (ylt_refletable_v<T>) {
size_t pos;
uint32_t size = detail::decode_varint(pb_str, pos);
pb_str = pb_str.substr(pos);
if (pb_str.size() < size)
IGUANA_UNLIKELY {
throw std::invalid_argument("Invalid fixed int value: too few bytes.");
}
if (size == 0) {
return;
}
from_pb(val, pb_str.substr(0, size));
pb_str = pb_str.substr(size);
}
else if constexpr (is_sequence_container<T>::value) {
using item_type = typename T::value_type;
if constexpr (is_lenprefix_v<item_type>) {
// item_type non-packed
while (!pb_str.empty()) {
item_type item{};
from_pb_impl(item, pb_str);
val.push_back(std::move(item));
if (pb_str.empty()) {
break;
}
uint32_t key = detail::decode_varint(pb_str, pos);
uint32_t field_number = key >> 3;
if (field_number != field_no) {
break;
}
else {
pb_str = pb_str.substr(pos);
}
}
}
else {
// item_type packed
size_t pos;
uint32_t size = detail::decode_varint(pb_str, pos);
pb_str = pb_str.substr(pos);
if (pb_str.size() < size)
IGUANA_UNLIKELY {
throw std::invalid_argument(
"Invalid fixed int value: too few bytes.");
}
if constexpr (is_fixed_v<item_type>) {
int num = size / sizeof(item_type);
int old_size = val.size();
detail::resize(val, old_size + num);
std::memcpy(val.data() + old_size, pb_str.data(), size);
pb_str = pb_str.substr(size);
}
else {
size_t start = pb_str.size();
while (!pb_str.empty()) {
item_type item;
from_pb_impl(item, pb_str);
val.push_back(std::move(item));
if (start - pb_str.size() == size) {
break;
}
}
}
}
}
else if constexpr (is_map_container<T>::value) {
using item_type = std::pair<typename T::key_type, typename T::mapped_type>;
while (!pb_str.empty()) {
size_t pos;
uint32_t size = detail::decode_varint(pb_str, pos);
pb_str = pb_str.substr(pos);
if (pb_str.size() < size)
IGUANA_UNLIKELY {
throw std::invalid_argument(
"Invalid fixed int value: too few bytes.");
}
item_type item = {};
decode_pair_value(item.first, pb_str);
decode_pair_value(item.second, pb_str);
val.emplace(std::move(item));
if (pb_str.empty()) {
break;
}
uint32_t key = detail::decode_varint(pb_str, pos);
uint32_t field_number = key >> 3;
if (field_number != field_no) {
break;
}
pb_str = pb_str.substr(pos);
}
}
else if constexpr (std::is_integral_v<T>) {
val = static_cast<T>(detail::decode_varint(pb_str, pos));
pb_str = pb_str.substr(pos);
}
else if constexpr (detail::is_signed_varint_v<T>) {
constexpr size_t len = sizeof(typename T::value_type);
uint64_t temp = detail::decode_varint(pb_str, pos);
if constexpr (len == 8) {
val.val = detail::decode_zigzag(temp);
}
else {
val.val = detail::decode_zigzag(static_cast<uint32_t>(temp));
}
pb_str = pb_str.substr(pos);
}
else if constexpr (detail::is_fixed_v<T>) {
constexpr size_t size = sizeof(typename T::value_type);
if (pb_str.size() < size)
IGUANA_UNLIKELY {
throw std::invalid_argument("Invalid fixed int value: too few bytes.");
}
memcpy(&(val.val), pb_str.data(), size);
pb_str = pb_str.substr(size);
}
else if constexpr (std::is_same_v<T, double> || std::is_same_v<T, float>) {
constexpr size_t size = sizeof(T);
if (pb_str.size() < size)
IGUANA_UNLIKELY {
throw std::invalid_argument("Invalid fixed int value: too few bytes.");
}
memcpy(&(val), pb_str.data(), size);
pb_str = pb_str.substr(size);
}
else if constexpr (std::is_same_v<T, std::string> ||
std::is_same_v<T, std::string_view>) {
size_t size = detail::decode_varint(pb_str, pos);
if (pb_str.size() < pos + size)
IGUANA_UNLIKELY {
throw std::invalid_argument("Invalid string value: too few bytes.");
}
if constexpr (std::is_same_v<T, std::string_view>) {
val = std::string_view(pb_str.data() + pos, size);
}
else {
detail::resize(val, size);
memcpy(val.data(), pb_str.data() + pos, size);
}
pb_str = pb_str.substr(size + pos);
}
else if constexpr (std::is_enum_v<T>) {
using U = std::underlying_type_t<T>;
U value{};
from_pb_impl(value, pb_str);
val = static_cast<T>(value);
}
else if constexpr (optional_v<T>) {
from_pb_impl(val.emplace(), pb_str);
}
else {
static_assert(!sizeof(T), "err");
}
}