#ifndef MATADOR_PK_FIELD_LOCATOR_HPP #define MATADOR_PK_FIELD_LOCATOR_HPP #include "matador/utils/primary_key_attribute.hpp" #include "matador/utils/field_attributes.hpp" #include "matador/utils/foreign_attributes.hpp" #include #include #include #include namespace matador::object::detail { using uuid16 = std::array; using pk_value = std::variant; enum class pk_kind { integer, string, uuid }; struct pk_field_descriptor { std::size_t offset{}; pk_kind kind{pk_kind::integer}; bool (*is_known_at)(const void* obj, std::size_t offset) = nullptr; pk_value (*get_at)(const void* obj, std::size_t offset) = nullptr; void (*set_at)(void* obj, std::size_t offset, const pk_value& v) = nullptr; }; template < typename Type > struct pk_field_locator { Type *base{nullptr}; pk_field_descriptor desc{}; bool found{false}; explicit pk_field_locator (Type &obj) : base(&obj) {} template void on_primary_key(const char *, PrimaryKeyType &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) { // Offset bestimmen const auto* obj_bytes = reinterpret_cast(base); const auto* pk_bytes = reinterpret_cast(&pk); desc.offset = static_cast(pk_bytes - obj_bytes); if constexpr (std::is_integral_v || std::is_enum_v) { desc.kind = pk_kind::integer; desc.is_known_at = [](void *obj, const std::size_t off) -> bool { auto *p = reinterpret_cast(static_cast(obj) + off); return *p != PrimaryKeyType{}; }; desc.get_at = [](void *obj, const std::size_t off) -> pk_value { auto *p = reinterpret_cast(static_cast(obj) + off); return static_cast(*p); }; desc.set_at = [](void *obj, const std::size_t off, const pk_value &v) { auto *p = reinterpret_cast(static_cast(obj) + off); if (auto *i = std::get_if(&v)) { *p = static_cast(*i); } else { throw std::logic_error("PK type mismatch: expected integer"); } }; } else if constexpr (std::is_same_v) { desc.kind = pk_kind::string; desc.is_known_at = [](void *obj, const std::size_t off) -> bool { const auto *p = reinterpret_cast(static_cast(obj) + off); return !p->empty(); }; desc.get_at = [](void *obj, const std::size_t off) -> pk_value { auto *p = reinterpret_cast(static_cast(obj) + off); return *p; }; desc.set_at = [](void *obj, const std::size_t off, const pk_value &v) { auto *p = reinterpret_cast(static_cast(obj) + off); if (auto *s = std::get_if(&v)) { *p = *s; } else { throw std::logic_error("PK type mismatch: expected string"); } }; } else if constexpr (std::is_same_v) { desc.kind = pk_kind::uuid; desc.is_known_at = [](void *obj, const std::size_t off) -> bool { auto *p = reinterpret_cast(static_cast(obj) + off); // “unknown” = all zeros for (auto b: *p) { if (b != 0) return true; } return false; }; desc.get_at = [](void *obj, const std::size_t off) -> pk_value { auto *p = reinterpret_cast(static_cast(obj) + off); return *p; }; desc.set_at = [](void *obj, const std::size_t off, const pk_value &v) { auto *p = reinterpret_cast(static_cast(obj) + off); if (auto *u = std::get_if(&v)) { *p = *u; } else { throw std::logic_error("PK type mismatch: expected uuid16"); } }; } else { throw std::logic_error("Unsupported primary key field type"); } found = true; } static void on_revision(const char *, std::uint64_t &) {} template static void on_attribute(const char *, V &, const utils::field_attributes & = matador::utils::null_attributes) {} template static void on_belongs_to(const char *, Pointer &, const utils::foreign_attributes &) {} template static void on_has_one(const char *, Pointer &, const utils::foreign_attributes &) {} template static void on_has_many(const char *, Container &, const char *, const utils::foreign_attributes &) {} template static void on_has_many_to_many(const char *, Container &, const char *, const char *,const utils::foreign_attributes &) {} template static void on_has_many_to_many(const char *, Container &, const utils::foreign_attributes &) {} }; } #endif //MATADOR_PK_FIELD_LOCATOR_HPP