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;
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);
102 template <
typename ...Elements>
103 Message& operator<<(
const std::variant<Elements...>& value);
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);
115 template <
typename _Enum,
typename = std::enable_if_t<std::is_enum_v<_Enum>>>
116 Message& operator<<(
const _Enum& item);
117 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
118 Message& operator<<(
const std::map<_Key, _Value, _Compare, _Allocator>& items);
119 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
120 Message& operator<<(
const std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items);
121 template <
typename... _ValueTypes>
122 Message& operator<<(
const Struct<_ValueTypes...>& item);
123 template <
typename... _ValueTypes>
124 Message& operator<<(
const std::tuple<_ValueTypes...>& item);
126 Message& operator>>(
bool& item);
127 Message& operator>>(int16_t& item);
128 Message& operator>>(int32_t& item);
129 Message& operator>>(int64_t& item);
130 Message& operator>>(uint8_t& item);
131 Message& operator>>(uint16_t& item);
132 Message& operator>>(uint32_t& item);
133 Message& operator>>(uint64_t& item);
134 Message& operator>>(
double& item);
135 Message& operator>>(
char*& item);
136 Message& operator>>(std::string &item);
138 template <
typename ...Elements>
139 Message& operator>>(std::variant<Elements...>& value);
143 template <
typename _Element,
typename _Allocator>
144 Message& operator>>(std::vector<_Element, _Allocator>& items);
145 template <
typename _Element, std::
size_t _Size>
146 Message& operator>>(std::array<_Element, _Size>& items);
148 template <
typename _Element, std::
size_t _Extent>
149 Message& operator>>(std::span<_Element, _Extent>& items);
151 template <
typename _Enum,
typename = std::enable_if_t<std::is_enum_v<_Enum>>>
152 Message& operator>>(_Enum& item);
153 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
154 Message& operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items);
155 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
156 Message& operator>>(std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items);
157 template <
typename... _ValueTypes>
158 Message& operator>>(Struct<_ValueTypes...>& item);
159 template <
typename... _ValueTypes>
160 Message& operator>>(std::tuple<_ValueTypes...>& item);
162 template <
typename _ElementType>
164 Message& openContainer(
const char* signature);
166 template <
typename _KeyType,
typename _ValueType>
168 Message& openDictEntry(
const char* signature);
170 template <
typename _ValueType>
172 Message& openVariant(
const char* signature);
174 template <
typename... _ValueTypes>
176 Message& openStruct(
const char* signature);
179 template <
typename _ElementType>
181 Message& enterContainer(
const char* signature);
183 template <
typename _KeyType,
typename _ValueType>
185 Message& enterDictEntry(
const char* signature);
187 template <
typename _ValueType>
189 Message& enterVariant(
const char* signature);
191 template <
typename... _ValueTypes>
193 Message& enterStruct(
const char* signature);
196 Message& appendArray(
char type,
const void *ptr,
size_t size);
197 Message& readArray(
char type,
const void **ptr,
size_t *size);
199 explicit operator bool()
const;
202 const char* getInterfaceName()
const;
203 const char* getMemberName()
const;
204 const char* getSender()
const;
205 const char* getPath()
const;
206 const char* getDestination()
const;
208 std::pair<char, const char*> peekType()
const;
209 bool isValid()
const;
210 bool isEmpty()
const;
211 bool isAtEnd(
bool complete)
const;
213 void copyTo(
Message& destination,
bool complete)
const;
215 void rewind(
bool complete);
217 pid_t getCredsPid()
const;
218 uid_t getCredsUid()
const;
219 uid_t getCredsEuid()
const;
220 gid_t getCredsGid()
const;
221 gid_t getCredsEgid()
const;
222 std::vector<gid_t> getCredsSupplementaryGids()
const;
223 std::string getSELinuxContext()
const;
228 template <
typename _Array>
229 void serializeArray(
const _Array& items);
230 template <
typename _Array>
231 void deserializeArray(_Array& items);
232 template <
typename _Array>
233 void deserializeArrayFast(_Array& items);
234 template <
typename _Element,
typename _Allocator>
235 void deserializeArrayFast(std::vector<_Element, _Allocator>& items);
236 template <
typename _Array>
237 void deserializeArraySlow(_Array& items);
238 template <
typename _Element,
typename _Allocator>
239 void deserializeArraySlow(std::vector<_Element, _Allocator>& items);
241 template <
typename _Dictionary>
242 void serializeDictionary(
const _Dictionary& items);
243 template <
typename _Dictionary>
244 void deserializeDictionary(_Dictionary& items);
248 explicit Message(internal::ISdBus* sdbus)
noexcept;
249 Message(
void *msg, internal::ISdBus* sdbus)
noexcept;
256 internal::ISdBus* sdbus_{};
257 mutable bool ok_{
true};
262 using Message::Message;
269 [[nodiscard]] Slot send(
void* callback,
void* userData, uint64_t timeout,
return_slot_t)
const;
274 void dontExpectReply();
275 bool doesntExpectReply()
const;
281 MethodReply sendWithReply(uint64_t timeout = 0)
const;
287 using Message::Message;
297 using Message::Message;
302 void setDestination(
const std::string& destination);
303 void setDestination(
const char* destination);
309 using Message::Message;
318 using Message::Message;
328 using Message::Message;
335 template <
typename ...Elements>
336 inline Message& Message::operator<<(
const std::variant<Elements...>& value)
338 std::visit([
this](
const auto& inner)
340 openVariant<decltype(inner)>();
348 template <
typename _Element,
typename _Allocator>
349 inline Message& Message::operator<<(
const std::vector<_Element, _Allocator>& items)
351 serializeArray(items);
356 template <
typename _Element, std::
size_t _Size>
357 inline Message& Message::operator<<(
const std::array<_Element, _Size>& items)
359 serializeArray(items);
365 template <
typename _Element, std::
size_t _Extent>
366 inline Message& Message::operator<<(
const std::span<_Element, _Extent>& items)
368 serializeArray(items);
374 template <
typename _Enum,
typename>
375 inline Message& Message::operator<<(
const _Enum &item)
377 return operator<<(
static_cast<std::underlying_type_t<_Enum>
>(item));
380 template <
typename _Array>
381 inline void Message::serializeArray(
const _Array& items)
383 using ElementType =
typename _Array::value_type;
387 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
389 constexpr auto signature = as_null_terminated(signature_of_v<ElementType>);
390 appendArray(*signature.data(), items.data(), items.size() *
sizeof(ElementType));
394 openContainer<ElementType>();
396 for (
const auto& item : items)
403 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
404 inline Message& Message::operator<<(
const std::map<_Key, _Value, _Compare, _Allocator>& items)
406 serializeDictionary(items);
411 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
412 inline Message& Message::operator<<(
const std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
414 serializeDictionary(items);
419 template <
typename _Dictionary>
420 inline void Message::serializeDictionary(
const _Dictionary& items)
422 using KeyType =
typename _Dictionary::key_type;
423 using MappedType =
typename _Dictionary::mapped_type;
425 openContainer<DictEntry<KeyType, MappedType>>();
427 for (
const auto& item : items)
429 openDictEntry<KeyType, MappedType>();
431 *
this << item.second;
440 template <
typename... _Args>
441 void serialize_pack(Message& msg, _Args&&... args)
443 (void)(msg << ... << args);
446 template <
class _Tuple, std::size_t... _Is>
447 void serialize_tuple( Message& msg
449 , std::index_sequence<_Is...>)
451 serialize_pack(msg, std::get<_Is>(t)...);
455 template <
typename... _ValueTypes>
456 inline Message& Message::operator<<(
const Struct<_ValueTypes...>& item)
458 openStruct<_ValueTypes...>();
459 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
465 template <
typename... _ValueTypes>
466 inline Message& Message::operator<<(
const std::tuple<_ValueTypes...>& item)
468 detail::serialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
474 template <
typename _Element,
typename... _Elements>
475 bool deserialize_variant(Message& msg, std::variant<_Elements...>& value,
const char* signature)
477 constexpr auto elemSignature = as_null_terminated(sdbus::signature_of_v<_Element>);
478 if (std::strcmp(signature, elemSignature.data()) != 0)
482 msg.enterVariant(signature);
485 value = std::move(temp);
490 template <
typename... Elements>
491 inline Message& Message::operator>>(std::variant<Elements...>& value)
493 auto [type, contents] = peekType();
494 bool result = (detail::deserialize_variant<Elements>(*
this, value, contents) || ...);
495 SDBUS_THROW_ERROR_IF(!result,
"Failed to deserialize variant: signature did not match any of the variant types", EINVAL);
499 template <
typename _Element,
typename _Allocator>
500 inline Message& Message::operator>>(std::vector<_Element, _Allocator>& items)
502 deserializeArray(items);
507 template <
typename _Element, std::
size_t _Size>
508 inline Message& Message::operator>>(std::array<_Element, _Size>& items)
510 deserializeArray(items);
516 template <
typename _Element, std::
size_t _Extent>
517 inline Message& Message::operator>>(std::span<_Element, _Extent>& items)
519 deserializeArray(items);
525 template <
typename _Enum,
typename>
526 inline Message& Message::operator>>(_Enum& item)
528 std::underlying_type_t<_Enum> val;
530 item =
static_cast<_Enum
>(val);
534 template <
typename _Array>
535 inline void Message::deserializeArray(_Array& items)
537 using ElementType =
typename _Array::value_type;
541 if constexpr (signature_of<ElementType>::is_trivial_dbus_type && !std::is_same_v<ElementType, bool>)
543 deserializeArrayFast(items);
547 deserializeArraySlow(items);
551 template <
typename _Array>
552 inline void Message::deserializeArrayFast(_Array& items)
554 using ElementType =
typename _Array::value_type;
557 const ElementType* arrayPtr{};
559 constexpr auto signature = as_null_terminated(sdbus::signature_of_v<ElementType>);
560 readArray(*signature.data(), (
const void**)&arrayPtr, &arraySize);
562 size_t elementsInMsg = arraySize /
sizeof(ElementType);
563 bool notEnoughSpace = items.size() < elementsInMsg;
564 SDBUS_THROW_ERROR_IF(notEnoughSpace,
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
566 std::copy_n(arrayPtr, elementsInMsg, items.begin());
569 template <
typename _Element,
typename _Allocator>
570 void Message::deserializeArrayFast(std::vector<_Element, _Allocator>& items)
573 const _Element* arrayPtr{};
575 constexpr auto signature = as_null_terminated(sdbus::signature_of_v<_Element>);
576 readArray(*signature.data(), (
const void**)&arrayPtr, &arraySize);
578 items.insert(items.end(), arrayPtr, arrayPtr + (arraySize /
sizeof(_Element)));
581 template <
typename _Array>
582 inline void Message::deserializeArraySlow(_Array& items)
584 using ElementType =
typename _Array::value_type;
586 if(!enterContainer<ElementType>())
589 for (
auto& elem : items)
590 if (!(*this >> elem))
593 SDBUS_THROW_ERROR_IF(!isAtEnd(
false),
"Failed to deserialize array: not enough space in destination sequence", EINVAL);
600 template <
typename _Element,
typename _Allocator>
601 void Message::deserializeArraySlow(std::vector<_Element, _Allocator>& items)
603 if(!enterContainer<_Element>())
610 items.emplace_back(std::move(elem));
620 template <
typename _Key,
typename _Value,
typename _Compare,
typename _Allocator>
621 inline Message& Message::operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items)
623 deserializeDictionary(items);
628 template <
typename _Key,
typename _Value,
typename _Hash,
typename _KeyEqual,
typename _Allocator>
629 inline Message& Message::operator>>(std::unordered_map<_Key, _Value, _Hash, _KeyEqual, _Allocator>& items)
631 deserializeDictionary(items);
636 template <
typename _Dictionary>
637 inline void Message::deserializeDictionary(_Dictionary& items)
639 using KeyType =
typename _Dictionary::key_type;
640 using MappedType =
typename _Dictionary::mapped_type;
642 if (!enterContainer<DictEntry<KeyType, MappedType>>())
647 if (!enterDictEntry<KeyType, MappedType>())
652 *
this >> key >> value;
654 items.emplace(std::move(key), std::move(value));
666 template <
typename... _Args>
667 void deserialize_pack(Message& msg, _Args&... args)
669 (void)(msg >> ... >> args);
672 template <
class _Tuple, std::size_t... _Is>
673 void deserialize_tuple( Message& msg
675 , std::index_sequence<_Is...> )
677 deserialize_pack(msg, std::get<_Is>(t)...);
681 template <
typename... _ValueTypes>
682 inline Message& Message::operator>>(Struct<_ValueTypes...>& item)
684 if (!enterStruct<_ValueTypes...>())
687 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
694 template <
typename... _ValueTypes>
695 inline Message& Message::operator>>(std::tuple<_ValueTypes...>& item)
697 detail::deserialize_tuple(*
this, item, std::index_sequence_for<_ValueTypes...>{});
701 template <
typename _ElementType>
702 inline Message& Message::openContainer()
704 constexpr auto signature = as_null_terminated(signature_of_v<_ElementType>);
705 return openContainer(signature.data());
708 template <
typename _KeyType,
typename _ValueType>
709 inline Message& Message::openDictEntry()
711 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_KeyType, _ValueType>>);
712 return openDictEntry(signature.data());
715 template <
typename _ValueType>
716 inline Message& Message::openVariant()
718 constexpr auto signature = as_null_terminated(signature_of_v<_ValueType>);
719 return openVariant(signature.data());
722 template <
typename... _ValueTypes>
723 inline Message& Message::openStruct()
725 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_ValueTypes...>>);
726 return openStruct(signature.data());
729 template <
typename _ElementType>
730 inline Message& Message::enterContainer()
732 constexpr auto signature = as_null_terminated(signature_of_v<_ElementType>);
733 return enterContainer(signature.data());
736 template <
typename _KeyType,
typename _ValueType>
737 inline Message& Message::enterDictEntry()
739 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_KeyType, _ValueType>>);
740 return enterDictEntry(signature.data());
743 template <
typename _ValueType>
744 inline Message& Message::enterVariant()
746 constexpr auto signature = as_null_terminated(signature_of_v<_ValueType>);
747 return enterVariant(signature.data());
750 template <
typename... _ValueTypes>
751 inline Message& Message::enterStruct()
753 constexpr auto signature = as_null_terminated(signature_of_v<std::tuple<_ValueTypes...>>);
754 return enterStruct(signature.data());
Definition TypeTraits.h:94
Definition TypeTraits.h:88