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 ({} <= {} <= {})", 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(), std::numeric_limits<
float>::max());
40 return static_cast<
float>(x);
43template <
typename Dst,
typename Value,
typename Src>
44Dst NarrowToInt(Src x,
const Value& value) {
46 std::numeric_limits<Src>::min() <= std::numeric_limits<Dst>::min() &&
47 std::numeric_limits<Src>::max() >= std::numeric_limits<Dst>::max(),
48 "expanding cast requested"
51 CheckInBounds<Src>(value, x, std::numeric_limits<Dst>::min(), std::numeric_limits<Dst>::max());
52 return static_cast<Dst>(x);
55template <
typename Value>
56std::chrono::seconds ToSeconds(
const std::string& data,
const Value& value) {
57 const auto ms = utils::StringToDuration(data);
58 const auto converted = std::chrono::duration_cast<std::chrono::seconds>(ms);
59 if (converted != ms) {
60 throw typename Value::ParseException(fmt::format(
61 "Value of '{}' = {}ms cannot be represented as "
62 "'std::chrono::seconds' without precision loss",
72template <
typename Value>
73float Parse(
const Value& value,
To<
float>) {
74 return impl::NarrowToFloat(value.
template As<
double>(), value);
77template <
typename Value,
typename T>
78std::enable_if_t<common::kIsFormatValue<Value> && meta::kIsInteger<T>, T> Parse(
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);
89template <
typename Value>
100template <
class Value>
105template <
typename Value,
typename T>
111template <
typename Value>