aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/misc/cast-inl.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/yt/misc/cast-inl.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/yt/misc/cast-inl.h')
-rw-r--r--library/cpp/yt/misc/cast-inl.h113
1 files changed, 113 insertions, 0 deletions
diff --git a/library/cpp/yt/misc/cast-inl.h b/library/cpp/yt/misc/cast-inl.h
new file mode 100644
index 0000000000..1920b7c0b7
--- /dev/null
+++ b/library/cpp/yt/misc/cast-inl.h
@@ -0,0 +1,113 @@
+#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 <util/string/cast.h>
+#include <util/string/printf.h>
+
+#include <type_traits>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace NDetail {
+
+template <class T, class S>
+typename std::enable_if<std::is_signed<T>::value && std::is_signed<S>::value, bool>::type IsInIntegralRange(S value)
+{
+ return value >= std::numeric_limits<T>::min() && value <= std::numeric_limits<T>::max();
+}
+
+template <class T, class S>
+static typename std::enable_if<std::is_signed<T>::value && std::is_unsigned<S>::value, bool>::type IsInIntegralRange(S value)
+{
+ return value <= static_cast<typename std::make_unsigned<T>::type>(std::numeric_limits<T>::max());
+}
+
+template <class T, class S>
+static typename std::enable_if<std::is_unsigned<T>::value && std::is_signed<S>::value, bool>::type IsInIntegralRange(S value)
+{
+ return value >= 0 && static_cast<typename std::make_unsigned<S>::type>(value) <= std::numeric_limits<T>::max();
+}
+
+template <class T, class S>
+typename std::enable_if<std::is_unsigned<T>::value && std::is_unsigned<S>::value, bool>::type IsInIntegralRange(S value)
+{
+ return value <= std::numeric_limits<T>::max();
+}
+
+template <class T>
+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<unsigned char>(value));
+}
+#endif
+
+} // namespace NDetail
+
+template <class T, class S>
+bool TryIntegralCast(S value, T* result)
+{
+ if (!NDetail::IsInIntegralRange<T>(value)) {
+ return false;
+ }
+ *result = static_cast<T>(value);
+ return true;
+}
+
+template <class T, class S>
+T CheckedIntegralCast(S value)
+{
+ T result;
+ if (!TryIntegralCast<T>(value, &result)) {
+ throw TSimpleException(Sprintf("Argument value %s is out of expected range",
+ NDetail::FormatInvalidCastValue(value).c_str()));
+ }
+ return result;
+}
+
+template <class T, class S>
+bool TryEnumCast(S value, T* result)
+{
+ auto candidate = static_cast<T>(value);
+ if (!TEnumTraits<T>::FindLiteralByValue(candidate)) {
+ return false;
+ }
+ *result = candidate;
+ return true;
+}
+
+template <class T, class S>
+T CheckedEnumCast(S value)
+{
+ T result;
+ if (!TryEnumCast<T>(value, &result)) {
+ throw TSimpleException(Sprintf("Invalid value %d of enum type %s",
+ static_cast<int>(value),
+ TEnumTraits<T>::GetTypeName().data()));
+ }
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT