27#ifndef SDBUS_CXX_MESSAGE_H_
28#define SDBUS_CXX_MESSAGE_H_
41# if __has_include(<span>)
47#include <unordered_map>
57 template <
typename... ValueTypes>
class Struct;
80 class [[nodiscard]] Message
83 Message(
const Message&)
noexcept;
84 Message& operator=(
const Message&)
noexcept;
85 Message(Message&& other)
noexcept;
86 Message& operator=(Message&& other)
noexcept;
89 Message& operator<<(
bool item);
90 Message& operator<<(int16_t item);
91 Message& operator<<(int32_t item);
92 Message& operator<<(int64_t item);
93 Message& operator<<(uint8_t item);
94 Message& operator<<(uint16_t item);
95 Message& operator<<(uint32_t item);
96 Message& operator<<(uint64_t item);
97 Message& operator<<(
double item);
98 Message& operator<<(
const char *item);
99 Message& operator<<(
const std::string &item);
100 Message& operator<<(std::string_view item);
101 Message& operator<<(
const Variant &item);
102 template <
typename ...Elements>
103 Message& operator<<(
const std::variant<Elements...>& value);
105 Message& operator<<(
const Signature &item);
106 Message& operator<<(
const UnixFd &item);
107 template <
typename Element,
typename Allocator>
108 Message& operator<<(
const std::vector<Element, Allocator>& items);
109 template <
typename Element, std::
size_t Size>
110 Message& operator<<(
const std::array<Element, Size>& items);
112 template <
typename Element, std::
size_t Extent>
113 Message& operator<<(
const std::span<Element, Extent>& items);
116 template <
typename Enum,
typename = std::enable_if_t<std::is_enum_v<Enum>>>
117 Message& operator<<(
const Enum& item);
118 template <
typename Key,
typename Value>
120 template <
typename Key,
typename Value,
typename Compare,
typename Allocator>
121 Message& operator<<(
const std::map<Key, Value, Compare, Allocator>& items);
122 template <
typename Key,
typename Value,
typename Hash,
typename KeyEqual,
typename Allocator>
123 Message& operator<<(
const std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& items);
124 template <
typename... ValueTypes>
126 template <
typename... ValueTypes>
127 Message& operator<<(
const std::tuple<ValueTypes...>& item);
129 Message& operator>>(
bool& item);
130 Message& operator>>(int16_t& item);
131 Message& operator>>(int32_t& item);
132 Message& operator>>(int64_t& item);
133 Message& operator>>(uint8_t& item);
134 Message& operator>>(uint16_t& item);
135 Message& operator>>(uint32_t& item);
136 Message& operator>>(uint64_t& item);
137 Message& operator>>(
double& item);
138 Message& operator>>(
char*& item);
139 Message& operator>>(std::string &item);
140 Message& operator>>(
Variant &item);
141 template <
typename ...Elements>
142 Message& operator>>(std::variant<Elements...>& value);
145 Message& operator>>(
UnixFd &item);
146 template <
typename Element,
typename Allocator>
147 Message& operator>>(std::vector<Element, Allocator>& items);
148 template <
typename Element, std::
size_t Size>
149 Message& operator>>(std::array<Element, Size>& items);
151 template <
typename Element, std::
size_t Extent>
152 Message& operator>>(std::span<Element, Extent>& items);
155 template <
typename Enum,
typename = std::enable_if_t<std::is_enum_v<Enum>>>
156 Message& operator>>(Enum& item);
157 template <
typename Key,
typename Value>
159 template <
typename Key,
typename Value,
typename Compare,
typename Allocator>
160 Message& operator>>(std::map<Key, Value, Compare, Allocator>& items);
161 template <
typename Key,
typename Value,
typename Hash,
typename KeyEqual,
typename Allocator>
162 Message& operator>>(std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& items);
163 template <
typename... ValueTypes>
165 template <
typename... ValueTypes>
166 Message& operator>>(std::tuple<ValueTypes...>& item);
168 template <
typename ElementType>
169 Message& openContainer();
170 Message& openContainer(
const char* signature);
171 Message& closeContainer();
172 template <
typename KeyType,
typename ValueType>
173 Message& openDictEntry();
174 Message& openDictEntry(
const char* signature);
175 Message& closeDictEntry();
176 template <
typename ValueType>
177 Message& openVariant();
178 Message& openVariant(
const char* signature);
179 Message& closeVariant();
180 template <
typename... ValueTypes>
181 Message& openStruct();
182 Message& openStruct(
const char* signature);
183 Message& closeStruct();
185 template <
typename ElementType>
186 Message& enterContainer();
187 Message& enterContainer(
const char* signature);
188 Message& exitContainer();
189 template <
typename KeyType,
typename ValueType>
190 Message& enterDictEntry();
191 Message& enterDictEntry(
const char* signature);
192 Message& exitDictEntry();
193 template <
typename ValueType>
194 Message& enterVariant();
195 Message& enterVariant(
const char* signature);
196 Message& exitVariant();
197 template <
typename... ValueTypes>
198 Message& enterStruct();
199 Message& enterStruct(
const char* signature);
200 Message& exitStruct();
202 Message& appendArray(
char type,
const void *ptr,
size_t size);
203 Message& readArray(
char type,
const void **ptr,
size_t *size);
205 template <
typename Key,
typename Value,
typename Callback>
206 Message& serializeDictionary(
const Callback& callback);
207 template <
typename Key,
typename Value>
209 template <
typename Key,
typename Value,
typename Callback>
210 Message& deserializeDictionary(
const Callback& callback);
212 explicit operator bool()
const;
215 const char* getInterfaceName()
const;
216 const char* getMemberName()
const;
217 const char* getSender()
const;
218 const char* getPath()
const;
219 const char* getDestination()
const;
220 uint64_t getCookie()
const;
222 std::pair<char, const char*> peekType()
const;
223 bool isValid()
const;
224 bool isEmpty()
const;
225 bool isAtEnd(
bool complete)
const;
227 void copyTo(Message& destination,
bool complete)
const;
229 void rewind(
bool complete);
231 enum class DumpFlags : uint64_t
234 WithHeader = 1ULL << 0,
235 SubtreeOnly = 1ULL << 1,
236 SubtreeOnlyWithHeader = WithHeader | SubtreeOnly
238 [[nodiscard]] std::string dumpToString(DumpFlags flags)
const;
240 pid_t getCredsPid()
const;
241 uid_t getCredsUid()
const;
242 uid_t getCredsEuid()
const;
243 gid_t getCredsGid()
const;
244 gid_t getCredsEgid()
const;
245 std::vector<gid_t> getCredsSupplementaryGids()
const;
246 std::string getSELinuxContext()
const;
251 template <
typename Array>
252 void serializeArray(
const Array& items);
253 template <
typename Array>
254 void deserializeArray(Array& items);
255 template <
typename Array>
256 void deserializeArrayFast(Array& items);
257 template <
typename Element,
typename Allocator>
258 void deserializeArrayFast(std::vector<Element, Allocator>& items);
259 template <
typename Array>
260 void deserializeArraySlow(Array& items);
261 template <
typename Element,
typename Allocator>
262 void deserializeArraySlow(std::vector<Element, Allocator>& items);
266 explicit Message(internal::IConnection* connection)
noexcept;
267 Message(
void *msg, internal::IConnection* connection)
noexcept;
268 Message(
void *msg, internal::IConnection* connection,
adopt_message_t)
noexcept;
273 internal::IConnection* connection_{};
274 mutable bool ok_{
true};
277 class MethodCall :
public Message
279 using Message::Message;
283 MethodCall() =
default;
286 [[nodiscard]] Slot send(
void* callback,
void* userData, uint64_t timeout,
return_slot_t)
const;
291 void dontExpectReply();
292 bool doesntExpectReply()
const;
295 MethodCall(
void *msg, internal::IConnection* connection,
adopt_message_t)
noexcept;
298 MethodReply sendWithReply(uint64_t timeout = 0)
const;
302 class MethodReply :
public Message
304 using Message::Message;
308 MethodReply() =
default;
310 uint64_t getReplyCookie()
const;
313 class Signal :
public Message
315 using Message::Message;
320 void setDestination(
const std::string& destination);
321 void setDestination(
const char* destination);
325 class PropertySetCall :
public Message
327 using Message::Message;
331 PropertySetCall() =
default;
334 class PropertyGetReply :
public Message
336 using Message::Message;
340 PropertyGetReply() =
default;
344 class PlainMessage :
public Message
346 using Message::Message;
350 PlainMessage() =
default;
355 template <
typename ...Elements>
356 inline Message& Message::operator<<(
const std::variant<Elements...>& value)
358 std::visit([
this](
const auto& inner)
360 openVariant<decltype(inner)>();
368 template <
typename Element,
typename Allocator>
369 inline Message& Message::operator<<(
const std::vector<Element, Allocator>& items)
371 serializeArray(items);
376 template <
typename Element, std::
size_t Size>
377 inline Message& Message::operator<<(
const std::array<Element, Size>& items)
379 serializeArray(items);
385 template <
typename Element, std::
size_t Extent>
386 inline Message& Message::operator<<(
const std::span<Element, Extent>& items)
388 serializeArray(items);
394 template <
typename Enum,
typename>
395 inline Message& Message::operator<<(
const Enum &item)
397 return operator<<(
static_cast<std::underlying_type_t<Enum>
>(item));
400 template <
typename Array>
401 inline void Message::serializeArray(
const Array& items)
403 using ElementType =
typename Array::value_type;
407 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
409 constexpr auto signature = as_null_terminated(signature_of_v<ElementType>);
410 appendArray(*signature.data(), items.data(), items.size() *
sizeof(ElementType));
414 openContainer<ElementType>();
416 for (
const auto& item : items)
423 template <
typename Key,
typename Value>
426 openDictEntry<Key, Value>();
427 *
this << value.first;
428 *
this << value.second;
434 template <
typename Key,
typename Value,
typename Compare,
typename Allocator>
435 inline Message& Message::operator<<(
const std::map<Key, Value, Compare, Allocator>& items)
437 serializeDictionary<Key, Value>([&items](Message& msg){
for (
const auto& item : items) msg << item; });
442 template <
typename Key,
typename Value,
typename Hash,
typename KeyEqual,
typename Allocator>
443 inline Message& Message::operator<<(
const std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& items)
445 serializeDictionary<Key, Value>([&items](Message& msg){
for (
const auto& item : items) msg << item; });
450 template <
typename Key,
typename Value>
453 serializeDictionary<Key, Value>([&](Message& msg){
for (
const auto& entry : dictEntries) msg << entry; });
458 template <
typename Key,
typename Value,
typename Callback>
459 inline Message& Message::serializeDictionary(
const Callback& callback)
461 openContainer<DictEntry<Key, Value>>();
470 template <
typename... Args>
471 void serialize_pack(Message& msg, Args&&... args)
473 (void)(msg << ... << std::forward<Args>(args));
476 template <
class Tuple, std::size_t... Is>
477 void serialize_tuple( Message& msg
479 , std::index_sequence<Is...>)
481 serialize_pack(msg, std::get<Is>(tuple)...);
485 template <
typename... ValueTypes>
488 openStruct<ValueTypes...>();
489 detail::serialize_tuple(*
this, item, std::index_sequence_for<ValueTypes...>{});
495 template <
typename... ValueTypes>
496 inline Message& Message::operator<<(
const std::tuple<ValueTypes...>& item)
498 detail::serialize_tuple(*
this, item, std::index_sequence_for<ValueTypes...>{});
504 template <
typename Element,
typename... Elements>
505 bool deserialize_variant(Message& msg, std::variant<Elements...>& value,
const char* signature)
507 constexpr auto elemSignature = as_null_terminated(signature_of_v<Element>);
508 if (std::strcmp(signature, elemSignature.data()) != 0)
512 msg.enterVariant(signature);
515 value = std::move(temp);
520 template <
typename... Elements>
521 inline Message& Message::operator>>(std::variant<Elements...>& value)
523 auto [type, contents] = peekType();
524 const bool result = (detail::deserialize_variant<Elements>(*
this, value, contents) || ...);
525 SDBUS_THROW_ERROR_IF(!result,
"Failed to deserialize variant: signature did not match any of the variant types", EINVAL);
529 template <
typename Element,
typename Allocator>
530 inline Message& Message::operator>>(std::vector<Element, Allocator>& items)
532 deserializeArray(items);
537 template <
typename Element, std::
size_t Size>
538 inline Message& Message::operator>>(std::array<Element, Size>& items)
540 deserializeArray(items);
546 template <
typename Element, std::
size_t Extent>
547 inline Message& Message::operator>>(std::span<Element, Extent>& items)
549 deserializeArray(items);
555 template <
typename Enum,
typename>
556 inline Message& Message::operator>>(Enum& item)
558 std::underlying_type_t<Enum> val;
560 item =
static_cast<Enum
>(val);
564 template <
typename Array>
565 inline void Message::deserializeArray(Array& items)
567 using ElementType =
typename Array::value_type;
571 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
573 deserializeArrayFast(items);
577 deserializeArraySlow(items);
581 template <
typename Array>
582 inline void Message::deserializeArrayFast(Array& items)
584 using ElementType =
typename Array::value_type;
587 const ElementType* arrayPtr{};
589 constexpr auto signature = as_null_terminated(signature_of_v<ElementType>);
590 readArray(*signature.data(),
reinterpret_cast<const void**
>(&arrayPtr), &arraySize);
592 const size_t elementsInMsg = arraySize /
sizeof(ElementType);
593 const bool notEnoughSpace = items.size() < elementsInMsg;
594 SDBUS_THROW_ERROR_IF(notEnoughSpace,
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
596 std::copy_n(arrayPtr, elementsInMsg, items.begin());
599 template <
typename Element,
typename Allocator>
600 void Message::deserializeArrayFast(std::vector<Element, Allocator>& items)
603 const Element* arrayPtr{};
605 constexpr auto signature = as_null_terminated(signature_of_v<Element>);
606 readArray(*signature.data(),
reinterpret_cast<const void**
>(&arrayPtr), &arraySize);
609 items.insert(items.end(), arrayPtr, arrayPtr + (arraySize /
sizeof(Element)));
612 template <
typename Array>
613 inline void Message::deserializeArraySlow(Array& items)
615 using ElementType =
typename Array::value_type;
617 if(!enterContainer<ElementType>())
620 for (
auto& elem : items)
621 if (!(*
this >> elem))
624 SDBUS_THROW_ERROR_IF(!isAtEnd(
false),
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
631 template <
typename Element,
typename Allocator>
632 void Message::deserializeArraySlow(std::vector<Element, Allocator>& items)
634 if(!enterContainer<Element>())
641 items.emplace_back(std::move(elem));
651 template <
typename Key,
typename Value>
654 if (!enterDictEntry<Key, Value>())
656 *
this >> value.first >> value.second;
662 template <
typename Key,
typename Value,
typename Compare,
typename Allocator>
663 inline Message& Message::operator>>(std::map<Key, Value, Compare, Allocator>& items)
665 deserializeDictionary<Key, Value>([&items](
auto dictEntry){ items.insert(std::move(dictEntry)); });
670 template <
typename Key,
typename Value,
typename Hash,
typename KeyEqual,
typename Allocator>
671 inline Message& Message::operator>>(std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& items)
673 deserializeDictionary<Key, Value>([&items](
auto dictEntry){ items.insert(std::move(dictEntry)); });
678 template <
typename Key,
typename Value,
typename Callback>
679 inline Message& Message::deserializeDictionary(
const Callback& callback)
681 if (!enterContainer<DictEntry<Key, Value>>())
686 DictEntry<Key, Value> dictEntry;
690 callback(std::move(dictEntry));
701 template <
typename... Args>
702 void deserialize_pack(Message& msg, Args&... args)
704 (void)(msg >> ... >> args);
707 template <
class Tuple, std::size_t... Is>
708 void deserialize_tuple( Message& msg
710 , std::index_sequence<Is...> )
712 deserialize_pack(msg, std::get<Is>(tuple)...);
716 template <
typename... ValueTypes>
719 if (!enterStruct<ValueTypes...>())
722 detail::deserialize_tuple(*
this, item, std::index_sequence_for<ValueTypes...>{});
729 template <
typename... ValueTypes>
730 inline Message& Message::operator>>(std::tuple<ValueTypes...>& item)
732 detail::deserialize_tuple(*
this, item, std::index_sequence_for<ValueTypes...>{});
736 template <
typename ElementType>
737 inline Message& Message::openContainer()
739 constexpr auto signature = as_null_terminated(signature_of_v<ElementType>);
740 return openContainer(signature.data());
743 template <
typename KeyType,
typename ValueType>
744 inline Message& Message::openDictEntry()
746 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<KeyType, ValueType>>);
747 return openDictEntry(signature.data());
750 template <
typename ValueType>
751 inline Message& Message::openVariant()
753 constexpr auto signature = as_null_terminated(signature_of_v<ValueType>);
754 return openVariant(signature.data());
757 template <
typename... ValueTypes>
758 inline Message& Message::openStruct()
760 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<ValueTypes...>>);
761 return openStruct(signature.data());
764 template <
typename ElementType>
765 inline Message& Message::enterContainer()
767 constexpr auto signature = as_null_terminated(signature_of_v<ElementType>);
768 return enterContainer(signature.data());
771 template <
typename KeyType,
typename ValueType>
772 inline Message& Message::enterDictEntry()
774 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<KeyType, ValueType>>);
775 return enterDictEntry(signature.data());
778 template <
typename ValueType>
779 inline Message& Message::enterVariant()
781 constexpr auto signature = as_null_terminated(signature_of_v<ValueType>);
782 return enterVariant(signature.data());
785 template <
typename... ValueTypes>
786 inline Message& Message::enterStruct()
788 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<ValueTypes...>>);
789 return enterStruct(signature.data());
std::pair< T1, T2 > DictEntry
Definition Types.h:415
Definition TypeTraits.h:94
Definition TypeTraits.h:88