#ifndef CAST_INL_H_ #error "Direct inclusion of this file is not allowed, include cast.h" // For the sake of sane code completion. #include "cast.h" #endif #include "enum.h" #include #include #include #include namespace NYT { //////////////////////////////////////////////////////////////////////////////// namespace NDetail { template bool IsInIntegralRange(S value) requires std::is_signed_v && std::is_signed_v { return value >= std::numeric_limits::min() && value <= std::numeric_limits::max(); } template bool IsInIntegralRange(S value) requires std::is_signed_v && std::is_unsigned_v { return value <= static_cast::type>(std::numeric_limits::max()); } template bool IsInIntegralRange(S value) requires std::is_unsigned_v && std::is_signed_v { return value >= 0 && static_cast::type>(value) <= std::numeric_limits::max(); } template bool IsInIntegralRange(S value) requires std::is_unsigned_v && std::is_unsigned_v { return value <= std::numeric_limits::max(); } template bool IsInIntegralRange(S value) requires std::is_enum_v { return IsInIntegralRange(static_cast>(value)); } template TString FormatInvalidCastValue(T value) { return ::ToString(value); } inline TString FormatInvalidCastValue(signed char value) { return TString("'") + value + TString("'"); } inline TString FormatInvalidCastValue(unsigned char value) { return TString("'") + value + TString("'"); } #ifdef __cpp_char8_t inline TString FormatInvalidCastValue(char8_t value) { return FormatInvalidCastValue(static_cast(value)); } #endif } // namespace NDetail template bool TryIntegralCast(S value, T* result) { if (!NYT::NDetail::IsInIntegralRange(value)) { return false; } *result = static_cast(value); return true; } template T CheckedIntegralCast(S value) { T result; if (!TryIntegralCast(value, &result)) { throw TSimpleException(Sprintf("Argument value %s is out of expected range", NYT::NDetail::FormatInvalidCastValue(value).c_str())); } return result; } template bool TryEnumCast(S value, T* result) { std::underlying_type_t underlying; if (!TryIntegralCast>(value, &underlying)) { return false; } auto candidate = static_cast(underlying); if (!TEnumTraits::FindLiteralByValue(candidate)) { return false; } *result = candidate; return true; } template T CheckedEnumCast(S value) { T result; if (!TryEnumCast(value, &result)) { throw TSimpleException(Sprintf("Invalid value %d of enum type %s", static_cast(value), TEnumTraits::GetTypeName().data())); } return result; } //////////////////////////////////////////////////////////////////////////////// } // namespace NYT