// Glaze Library // For the license information refer to glaze.hpp #pragma once #include "glaze/glaze.hpp" #include "glaze/rpc/repe/repe.hpp" namespace glz { // Forward declaration of the registry template template struct registry; template <> struct protocol_storage { using type = std::unordered_map, detail::string_hash, std::equal_to<>>; }; // Implementation for REPE protocol template struct registry_impl { template static void register_endpoint(const sv path, T& value, RegistryType& reg) { reg.endpoints[path] = [&value](repe::state_view& state) mutable { if (state.has_body()) { if (read_params(value, state) == 0) { return; } } if (state.notify()) { return; } if (not state.has_body()) { write_response(value, state); } else { write_response(state); } }; } template static void register_function_endpoint(const sv path, Func& func, RegistryType& reg) { if constexpr (std::same_as) { reg.endpoints[path] = [&func](repe::state_view& state) mutable { func(); if (state.notify()) { return; } write_response(state); }; } else { reg.endpoints[path] = [&func](repe::state_view& state) mutable { if (state.notify()) { std::ignore = func(); return; } write_response(func(), state); }; } } template static void register_param_function_endpoint(const sv path, Func& func, RegistryType& reg) { reg.endpoints[path] = [&func](repe::state_view& state) mutable { static thread_local std::decay_t params{}; params = {}; // reset to avoid stale optional/variant fields across calls if (read_params(params, state) == 0) { return; } using Result = std::invoke_result_t; if (state.notify()) { if constexpr (std::same_as) { func(params); } else { std::ignore = func(params); } return; } if constexpr (std::same_as) { func(params); write_response(state); } else { auto ret = func(params); write_response(ret, state); } }; } template static void register_object_endpoint(const sv path, Obj& obj, RegistryType& reg) { reg.endpoints[path] = [&obj](repe::state_view& state) mutable { if (state.has_body()) { if (read_params(obj, state) == 0) { return; } } if (state.notify()) { return; } if (not state.has_body()) { write_response(obj, state); } else { write_response(state); } }; } template static void register_value_endpoint(const sv path, Value& value, RegistryType& reg) { reg.endpoints[path] = [value](repe::state_view& state) mutable { if (state.has_body()) { if (read_params(value, state) == 0) { return; } } if (state.notify()) { return; } if (not state.has_body()) { write_response(value, state); } else { write_response(state); } }; } template static void register_variable_endpoint(const sv path, Var& var, RegistryType& reg) { reg.endpoints[path] = [&var](repe::state_view& state) mutable { if (state.has_body()) { if (read_params(var, state) == 0) { return; } } if (state.notify()) { return; } if (not state.has_body()) { write_response(var, state); } else { write_response(state); } }; } template static void register_member_function_endpoint(const sv path, T& value, F func, RegistryType& reg) { reg.endpoints[path] = [&value, func](repe::state_view& state) mutable { if constexpr (std::same_as) { (value.*func)(); if (state.notify()) { return; } write_response(state); } else { if (state.notify()) { std::ignore = (value.*func)(); return; } write_response((value.*func)(), state); } }; } template static void register_member_function_with_params_endpoint(const sv path, T& value, F func, RegistryType& reg) { reg.endpoints[path] = [&value, func](repe::state_view& state) mutable { static thread_local Input input{}; input = {}; // reset to avoid stale optional/variant fields across calls if (state.has_body()) { if (read_params(input, state) == 0) { return; } } if constexpr (std::same_as) { (value.*func)(input); if (state.notify()) { return; } write_response(state); } else { if (state.notify()) { std::ignore = (value.*func)(input); return; } write_response((value.*func)(input), state); } }; } // Register a merged endpoint that combines multiple objects into a single response // Note: This endpoint is read-only; writing to it is not supported template static void register_merge_endpoint(const sv path, glz::merge& merged, RegistryType& reg) { reg.endpoints[path] = [&merged](repe::state_view& state) mutable { // Merged endpoints are read-only if (state.has_body()) { state.out.reset(state.in); state.out.set_error(error_code::invalid_body, "writing to merged endpoint is not supported"); return; } if (state.notify()) { return; } write_response(merged, state); }; } }; }