// Copyright 2026 Christian Granzin // Copyright 2008 Christophe Henry // henry UNDERSCORE christophe AT hotmail DOT com // This is an extended version of the state machine available in the boost::mpl library // Distributed under the same license as the original. // Copyright for the original version: // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed // under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MSM_BACKMP11_SERIALIZATION_BOOST_JSON_HPP #define BOOST_MSM_BACKMP11_SERIALIZATION_BOOST_JSON_HPP #include #include #include namespace boost::msm::backmp11::serialization { // Serializer for Boost.JSON. class boost_json_serializer { using json = boost::json::object; public: boost_json_serializer(boost::json::value& json) : m_json({&json.emplace_object()}) { } template void visit_front_end(FrontEnd&& front_end) { if constexpr (!std::is_empty_v>) { top()["front_end"] = boost::json::value_from(front_end); } } template void visit_front_end(FrontEnd&& /*front_end*/, Reflect&& reflect) { auto& json_front_end = top()["front_end"].emplace_object(); m_json.push(&json_front_end); reflect(); m_json.pop(); } template void visit_member(const char* key, Member&& member) { top()[key] = boost::json::value_from(member); } template void visit_member(const char* key, const std::array& member) { boost::json::array& arr = top()[key].emplace_array(); for (const auto& elem : member) { arr.push_back(elem); } } template void visit_state(size_t state_id, State&& state) { if constexpr (!std::is_empty_v>) { if (!top().contains("states")) { top()["states"].emplace_object(); } top()["states"].as_object()[std::to_string(state_id)] = boost::json::value_from(state); } } template void visit_state(size_t state_id, State&& /*state*/, Reflect&& reflect) { if (!top().contains("states")) { top()["states"].emplace_object(); } auto& json_state = top()["states"] .as_object()[std::to_string(state_id)] .emplace_object(); m_json.push(&json_state); reflect(); m_json.pop(); } private: json& top() { return *m_json.top(); } std::stack m_json; }; // Deserializer for Boost.JSON. class boost_json_deserializer { using json = boost::json::object; public: boost_json_deserializer(const boost::json::value& json) : m_json({&json.as_object()}) { } template void visit_front_end(FrontEnd&& front_end) { if constexpr (!std::is_empty_v>) { front_end = boost::json::value_to>( top().at("front_end")); } } template void visit_front_end(FrontEnd&& /*front_end*/, Reflect&& reflect) { auto& json_state = top().at("front_end").as_object(); m_json.push(&json_state); reflect(); m_json.pop(); } template void visit_member(const char* key, Member&& member) { member = boost::json::value_to>(top().at(key)); } template void visit_member(const char* key, std::array& member) { const auto& arr = top().at(key).as_array(); for (std::size_t i = 0; i < N; ++i) member[i] = boost::json::value_to(arr[i]); } template void visit_state(size_t state_id, State&& state) { if constexpr (!std::is_empty_v>) { state = boost::json::value_to>( top().at("states").at(std::to_string(state_id))); } } template void visit_state(size_t state_id, State& /*state*/, Reflect&& reflect) { auto& json_state = top().at("states").at(std::to_string(state_id)).as_object(); m_json.push(&json_state); reflect(); m_json.pop(); } private: const json& top() { return *m_json.top(); } std::stack m_json; }; } // namespace boost::msm::backmp11::serialization namespace boost::msm::backmp11 { inline void tag_invoke(const boost::json::value_from_tag&, boost::json::value& json, const machine_state& state) { json = static_cast>(state); } inline machine_state tag_invoke(const boost::json::value_to_tag&, const boost::json::value& json) { return static_cast( json.to_number>()); } template >> void tag_invoke(const boost::json::value_from_tag&, boost::json::value& json, const StateMachine& sm) { reflect(sm, serialization::boost_json_serializer{json}); } template >> StateMachine tag_invoke(const boost::json::value_to_tag&, const boost::json::value& json) { StateMachine state_machine; reflect(state_machine, serialization::boost_json_deserializer{json}); return state_machine; } } // namespace boost::msm::backmp11::detail #endif // BOOST_MSM_BACKMP11_SERIALIZATION_BOOST_JSON_HPP