From a6c4419da6f559cace4a0ee8a363f5f341cc9873 Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Sat, 25 Jul 2026 15:26:15 +0200 Subject: [PATCH] cast.hpp helper I was tired of manually bounds-checking my integer casts. --- files.cmake | 1 + include/helpers/cast.hpp | 48 ++++++++++++++++++++++++++++++++++++++++ src/helpers/cast.cpp | 14 ++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 include/helpers/cast.hpp create mode 100644 src/helpers/cast.cpp diff --git a/files.cmake b/files.cmake index c8c92c9b75..51b2bdf95e 100644 --- a/files.cmake +++ b/files.cmake @@ -1581,6 +1581,7 @@ set(DUSK_FILES src/helpers/endian.cpp src/helpers/offset_ptr.cpp src/helpers/string.cpp + src/helpers/cast.cpp ) set(DUSK_HTTP_BACKEND_FILES diff --git a/include/helpers/cast.hpp b/include/helpers/cast.hpp new file mode 100644 index 0000000000..206bc1e3f3 --- /dev/null +++ b/include/helpers/cast.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +/** + * Helper functions for performing casts. + */ +namespace dusk::helpers::cast { + /** + * Implementation details of dusk::helpers::cast. + */ + namespace _impl { + [[noreturn]] void overrun_high(); + [[noreturn]] void overrun_low(); + } + + template + concept IntCastable = std::is_integral_v && std::is_trivially_copyable_v; + + /** + * Helper type that allows easily casting between integer types, + * that safely aborts if an overflow were to occur. + * Usage: + * @code + * size_t foobar = 20; + * int real = bounded_cast(foobar); + * @endcode + */ + template + struct bounded_cast { + Source src; + + template + [[nodiscard]] constexpr operator Target() const { + if (std::cmp_greater(src, std::numeric_limits::max())) [[unlikely]] { + _impl::overrun_high(); + } + + if (std::cmp_less(src, std::numeric_limits::min())) [[unlikely]] { + _impl::overrun_low(); + } + + return static_cast(src); + } + }; +} diff --git a/src/helpers/cast.cpp b/src/helpers/cast.cpp new file mode 100644 index 0000000000..71eb3160de --- /dev/null +++ b/src/helpers/cast.cpp @@ -0,0 +1,14 @@ +#include "helpers/cast.hpp" +#include "global.h" + +namespace dusk::helpers::cast::_impl { + +void overrun_high() { + CRASH("bounded cast overran!"); +} + +void overrun_low() { + CRASH("bounded cast overran!"); +} + +} // namespace dusk::helpers::cast::_impl