IGUANA_INLINE void from_pb_impl()

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");
  }
}