13#include <fmt/format.h> 
   15#include <userver/formats/common/meta.hpp> 
   16#include <userver/formats/parse/to.hpp> 
   17#include <userver/utils/datetime.hpp> 
   18#include <userver/utils/datetime/from_string_saturating.hpp> 
   19#include <userver/utils/meta.hpp> 
   20#include <userver/utils/string_to_duration.hpp> 
   22USERVER_NAMESPACE_BEGIN
 
   25namespace formats::
parse {
 
   28template <
typename T, 
typename Value>
 
   29void CheckInBounds(
const Value& value, T x, T min, T max) {
 
   30  if (x < min || x > max) {
 
   31    throw typename Value::ParseException(
 
   32        fmt::format(
"Value of '{}' is out of bounds ({} <= {} <= {})",
 
   33                    value.GetPath(), min, x, max));
 
   37template <
typename Value>
 
   38float NarrowToFloat(
double x, 
const Value& value) {
 
   39  CheckInBounds<
double>(value, x, std::numeric_limits<
float>::lowest(),
 
   40                        std::numeric_limits<
float>::max());
 
   41  return static_cast<
float>(x);
 
   44template <
typename Dst, 
typename Value, 
typename Src>
 
   45Dst NarrowToInt(Src x, 
const Value& value) {
 
   47      std::numeric_limits<Src>::min() <= std::numeric_limits<Dst>::min() &&
 
   48          std::numeric_limits<Src>::max() >= std::numeric_limits<Dst>::max(),
 
   49      "expanding cast requested");
 
   51  CheckInBounds<Src>(value, x, std::numeric_limits<Dst>::min(),
 
   52                     std::numeric_limits<Dst>::max());
 
   53  return static_cast<Dst>(x);
 
   56template <
typename Value>
 
   57std::chrono::seconds ToSeconds(
const std::string& data, 
const Value& value) {
 
   59  const auto converted = std::chrono::duration_cast<std::chrono::seconds>(ms);
 
   60  if (converted != ms) {
 
   61    throw typename Value::ParseException(
 
   62        fmt::format(
"Value of '{}' = {}ms cannot be represented as " 
   63                    "'std::chrono::seconds' without precision loss",
 
   64                    value.GetPath(), ms.count()));
 
   71template <
typename Value>
 
   72float Parse(
const Value& value, 
To<
float>) {
 
   73  return impl::NarrowToFloat(value.
template As<
double>(), value);
 
   76template <
typename Value, 
typename T>
 
   77std::enable_if_t<common::kIsFormatValue<Value> && meta::kIsInteger<T>, T> Parse(
 
   78    const Value& value, To<T>) {
 
   79  using IntT = std::conditional_t<std::is_signed<T>::value, int64_t, uint64_t>;
 
   80  return impl::NarrowToInt<T>(value.
template As<IntT>(), value);
 
   83template <
typename Value, 
typename Period>
 
   84std::enable_if_t<common::kIsFormatValue<Value>,
 
   85                 std::chrono::duration<
double, Period>>
 
   86Parse(
const Value& n, To<std::chrono::duration<
double, Period>>) {
 
   87  return std::chrono::duration<
double, Period>(n.
template As<
double>());
 
   90template <
typename Value>
 
   91std::enable_if_t<common::kIsFormatValue<Value>, std::chrono::seconds> Parse(
 
   92    const Value& n, To<std::chrono::seconds>) {
 
   93  return n.IsInt64() ? std::chrono::seconds{n.
template As<int64_t>()}
 
   94                     : impl::ToSeconds(n.
template As<std::string>(), n);
 
   98std::chrono::system_clock::time_point Parse(
 
   99    const Value& n, 
To<std::chrono::system_clock::time_point>) {
 
  101      n.
template As<std::string>()
);
 
  104template <
class Value>
 
  105float Convert(
const Value& value, 
To<
float>) {
 
  106  return impl::NarrowToFloat(value.
template ConvertTo<
double>(), value);
 
  109template <
typename Value, 
typename T>
 
  110std::enable_if_t<meta::kIsInteger<T>, T> Convert(
const Value& value, To<T>) {
 
  111  using IntT = std::conditional_t<std::is_signed<T>::value, int64_t, uint64_t>;
 
  112  return impl::NarrowToInt<T>(value.
template ConvertTo<IntT>(), value);
 
  115template <
typename Value>
 
  116std::chrono::seconds Convert(
const Value& n, 
To<std::chrono::seconds>) {
 
  117  return n.IsInt64() ? std::chrono::seconds{n.
template ConvertTo<int64_t>()}
 
  118                     : impl::ToSeconds(n.
template ConvertTo<std::string>(), n);