summaryrefslogtreecommitdiff
path: root/src/sdbuscpp_no_throw_helper.hh
blob: 46968959f548fc25a74357b4c99b7b9508c7bf10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#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<STRUCT>                                                                                      \
      : signature_of<sdbus::Struct<SDBUSCPP_STRUCT_MEMBER_TYPES(                                                   \
            STRUCT, __VA_ARGS__)>> {};                                                                             \
                                                                                                                   \
  inline auto as_dictionary_if_struct(const STRUCT& object) {                                                      \
    return as_dictionary<STRUCT>(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<STRUCT>& s) {                                       \
    if constexpr (!nested_struct_as_dict_serialization_v<STRUCT>)                                                  \
      return msg.serializeDictionary<std::string, Variant>(                                                        \
          {SDBUSCPP_STRUCT_MEMBERS_AS_DICT_ENTRIES(s.m_struct, __VA_ARGS__)});                                     \
    else                                                                                                           \
      return msg.serializeDictionary<std::string, Variant>(                                                        \
          {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<STRUCT>::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<std::string, Variant>(                                                        \
        [&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