refactor(furvm): improve thing value access

This commit is contained in:
2026-09-04 21:19:03 +02:00
parent 0354ec1e79
commit 24a9530abc
3 changed files with 89 additions and 2 deletions
+8 -2
View File
@@ -96,11 +96,17 @@ public:
struct dynamic_array { struct dynamic_array {
std::size_t size; std::size_t size;
std::byte* data; std::byte* data;
static bool matches(const thing_type& type) {
return type.type == thing_type::Array && type.value.array.size == 0;
}
}; };
struct slice { struct slice {
std::size_t length; std::size_t length;
std::byte* data; std::byte* data;
static bool matches(const thing_type& type) { return type.type == thing_type::Slice; }
}; };
struct header { struct header {
@@ -407,7 +413,7 @@ public:
*/ */
template <typename T> template <typename T>
T& get() { T& get() {
if (compute_size_na(*m_type) != sizeof(T)) throw bad_thing_access(); if (!detail::thing_traits<T>{}(*m_type)) throw bad_thing_access();
return *std::launder(reinterpret_cast<T*>(m_data)); return *std::launder(reinterpret_cast<T*>(m_data));
} }
@@ -418,7 +424,7 @@ public:
*/ */
template <typename T> template <typename T>
const T& get() const { const T& get() const {
if (compute_size_na(*m_type) != sizeof(T)) throw bad_thing_access(); if (!detail::thing_traits<T>{}(*m_type)) throw bad_thing_access();
return *std::launder(reinterpret_cast<const T*>(m_data)); return *std::launder(reinterpret_cast<const T*>(m_data));
} }
public: public:
+72
View File
@@ -6,6 +6,8 @@
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <stdexcept> #include <stdexcept>
#include <type_traits>
#include <utility>
namespace furvm { namespace furvm {
@@ -127,6 +129,76 @@ struct thing_type {
} }
}; };
namespace detail {
template <typename T, typename = void>
struct overrides_thing_type_matching : std::false_type {};
template <typename T>
struct overrides_thing_type_matching<T, std::void_t<decltype(T::matches(std::declval<const thing_type&>()))>>
: std::is_same<decltype(T::matches(std::declval<const thing_type&>())), bool> {};
template <typename T>
struct thing_traits {
bool operator()(const thing_type& type) const {
if constexpr (overrides_thing_type_matching<T>::value) {
return T::matches(type);
} else {
return false;
}
}
};
template <>
struct thing_traits<s8> {
bool operator()(const thing_type& type) const { return type.type == thing_type::S8; }
};
template <>
struct thing_traits<u8> {
bool operator()(const thing_type& type) const { return type.type == thing_type::U8; }
};
template <>
struct thing_traits<s16> {
bool operator()(const thing_type& type) const { return type.type == thing_type::S16; }
};
template <>
struct thing_traits<u16> {
bool operator()(const thing_type& type) const { return type.type == thing_type::U16; }
};
template <>
struct thing_traits<s32> {
bool operator()(const thing_type& type) const { return type.type == thing_type::S32; }
};
template <>
struct thing_traits<u32> {
bool operator()(const thing_type& type) const { return type.type == thing_type::U32; }
};
template <>
struct thing_traits<s64> {
bool operator()(const thing_type& type) const { return type.type == thing_type::S64; }
};
template <>
struct thing_traits<u64> {
bool operator()(const thing_type& type) const { return type.type == thing_type::U64; }
};
template <typename Inner>
struct thing_traits<Inner*> {
bool operator()(const thing_type& type) const {
return (type.type == thing_type::Ptr || type.type == thing_type::Ref) &&
thing_traits<Inner>{}(*type.value.typeRef);
}
};
} // namespace detail
} // namespace furvm } // namespace furvm
#endif // FURVM_TYPES_HPP #endif // FURVM_TYPES_HPP
+9
View File
@@ -1,3 +1,4 @@
#include "furvm/exceptions.hpp"
#include "furvm/furvm.hpp" #include "furvm/furvm.hpp"
#include "furvm/thing.hpp" #include "furvm/thing.hpp"
@@ -77,4 +78,12 @@ TEST(ThingOps, Iterators) {
} }
} }
TEST(ThingOps, Access) {
furvm::thing thing{ furvm::thing_type{ furvm::thing_type::U8 } };
EXPECT_NO_THROW(thing.get<furvm::u8>());
EXPECT_THROW(thing.get<furvm::s8>(), furvm::bad_thing_access);
EXPECT_THROW(thing.get<furvm::s32>(), furvm::bad_thing_access);
EXPECT_THROW(thing.get<void*>(), furvm::bad_thing_access);
}
} // namespace } // namespace