#ifndef SDBUSCPP_NO_THROW_HELPER_HH #define SDBUSCPP_NO_THROW_HELPER_HH // SDBUSCPP_ENABLE_RELAXED_DICT2STRUCT_DESERIALIZATION + // SDBUSCPP_REGISTER_STRUCT still references throw #define SDBUSCPP_REGISTER_STRUCT_NO_THROW(STRUCT, ...) \ namespace sdbus { \ static_assert(SDBUSCPP_PP_NARG(__VA_ARGS__) <= 16, \ "Not more than 16 struct members are supported, please open " \ "an issue if you need more"); \ \ template <> \ struct signature_of \ : signature_of> {}; \ \ inline auto as_dictionary_if_struct(const STRUCT& object) { \ return as_dictionary(object); \ } \ \ inline sdbus::Message& operator<<(sdbus::Message& msg, \ const STRUCT& items) { \ return msg << sdbus::Struct{std::forward_as_tuple( \ SDBUSCPP_STRUCT_MEMBERS(items, __VA_ARGS__))}; \ } \ \ inline Message& operator<<(Message& msg, const as_dictionary& s) { \ if constexpr (!nested_struct_as_dict_serialization_v) \ return msg.serializeDictionary( \ {SDBUSCPP_STRUCT_MEMBERS_AS_DICT_ENTRIES(s.m_struct, __VA_ARGS__)}); \ else \ return msg.serializeDictionary( \ {SDBUSCPP_STRUCT_MEMBERS_AS_NESTED_DICT_ENTRIES(s.m_struct, \ __VA_ARGS__)}); \ } \ \ inline Message& operator>>(Message& msg, STRUCT& s) { \ /* First, try to deserialize as a struct */ \ if (msg.peekType().first == signature_of::type_value) { \ Struct sdbusStruct{ \ std::forward_as_tuple(SDBUSCPP_STRUCT_MEMBERS(s, __VA_ARGS__))}; \ return msg >> sdbusStruct; \ } \ \ /* Otherwise try to deserialize as a dictionary of strings to variants */ \ \ return msg.deserializeDictionary( \ [&s](const auto& dictEntry) { \ const std::string& key = \ dictEntry \ .first; /* Intentionally not using structured bindings */ \ const Variant& value = dictEntry.second; \ \ using namespace std::string_literals; \ /* This also handles members which are structs serialized as dict of strings to variants, recursively */ \ SDBUSCPP_FIND_AND_DESERIALIZE_STRUCT_MEMBERS(s, __VA_ARGS__); \ }); \ } \ } #endif // SDBUSCPP_NO_THROW_HELPER_HH