mirror of
https://github.com/Kistler-Group/sdbus-cpp.git
synced 2026-01-25 07:12:17 +01:00
feat: add support for dumping variant to string (#526)
This allows Message and Variant contents serialization to a string -- based on `sd_bus_message_dump` sd-bus API function.
This commit is contained in:
committed by
GitHub
parent
9f3e89eb6a
commit
c2bb343f8a
@@ -55,7 +55,7 @@ CheckOptions:
|
||||
- key: hicpp-move-const-arg.CheckTriviallyCopyableMove
|
||||
value: '0'
|
||||
- key: misc-include-cleaner.IgnoreHeaders
|
||||
value: 'systemd/.*|sdbus-c\+\+/.*|gtest/.*|gmock/.*|bits/chrono.h|bits/basic_string.h|time.h|poll.h|stdlib.h'
|
||||
value: 'systemd/.*|sdbus-c\+\+/.*|gtest/.*|gmock/.*|bits/chrono.h|bits/basic_string.h|time.h|poll.h|stdlib.h|stdio.h'
|
||||
- key: readability-simplify-boolean-expr.IgnoreMacros
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-rvalue-reference-param-not-moved.IgnoreUnnamedParams
|
||||
|
||||
@@ -228,6 +228,15 @@ namespace sdbus {
|
||||
void seal();
|
||||
void rewind(bool complete);
|
||||
|
||||
enum class DumpFlags : uint64_t // NOLINT(performance-enum-size): using size from sd-bus
|
||||
{
|
||||
Default = 0ULL,
|
||||
WithHeader = 1ULL << 0,
|
||||
SubtreeOnly = 1ULL << 1,
|
||||
SubtreeOnlyWithHeader = WithHeader | SubtreeOnly
|
||||
};
|
||||
[[nodiscard]] std::string dumpToString(DumpFlags flags) const;
|
||||
|
||||
pid_t getCredsPid() const;
|
||||
uid_t getCredsUid() const;
|
||||
uid_t getCredsEuid() const;
|
||||
@@ -260,7 +269,6 @@ namespace sdbus {
|
||||
|
||||
friend Factory;
|
||||
|
||||
|
||||
void* msg_{};
|
||||
internal::IConnection* connection_{};
|
||||
mutable bool ok_{true};
|
||||
|
||||
@@ -103,6 +103,13 @@ namespace sdbus {
|
||||
return val;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string dumpToString() const
|
||||
{
|
||||
msg_.rewind(false);
|
||||
|
||||
return msg_.dumpToString(Message::DumpFlags::SubtreeOnly);
|
||||
}
|
||||
|
||||
// Only allow conversion operator for true D-Bus type representations in C++
|
||||
// NOLINTNEXTLINE(modernize-use-constraints): TODO for future: Use `requires signature_of<_ValueType>::is_valid` (when we stop supporting C++17 in public API)
|
||||
template <typename ValueType, typename = std::enable_if_t<signature_of<ValueType>::is_valid>>
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
#include "ScopeGuard.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cstdint> // int16_t, uint64_t, ...
|
||||
#include <cstdio>
|
||||
#include <cstdlib> // atexit
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
@@ -628,6 +630,28 @@ void Message::rewind(bool complete)
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to rewind the message", -r);
|
||||
}
|
||||
|
||||
std::string Message::dumpToString(DumpFlags flags) const
|
||||
{
|
||||
#if LIBSYSTEMD_VERSION>=245 && !defined(SDBUS_basu)
|
||||
char* buffer{};
|
||||
SCOPE_EXIT{ free(buffer); }; // NOLINT(cppcoreguidelines-no-malloc,hicpp-no-malloc,cppcoreguidelines-owning-memory)
|
||||
size_t size{};
|
||||
|
||||
const std::unique_ptr<FILE, int(*)(FILE*)> stream{open_memstream(&buffer, &size), fclose};
|
||||
SDBUS_THROW_ERROR_IF(!stream, "Failed to open memory stream", errno);
|
||||
|
||||
auto r = sd_bus_message_dump(static_cast<sd_bus_message*>(msg_), stream.get(), static_cast<uint64_t>(flags));
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to dump the message", -r);
|
||||
|
||||
(void)fflush(stream.get());
|
||||
|
||||
return {buffer, size};
|
||||
#else
|
||||
(void)flags;
|
||||
throw Error(Error::Name{SD_BUS_ERROR_NOT_SUPPORTED}, "Dumping sd-bus message not supported by underlying version of libsystemd");
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* Message::getInterfaceName() const
|
||||
{
|
||||
return sd_bus_message_get_interface(static_cast<sd_bus_message*>(msg_));
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
using ::testing::Eq;
|
||||
using ::testing::Gt;
|
||||
using ::testing::HasSubstr;
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace
|
||||
@@ -148,6 +149,24 @@ TEST(ASimpleVariant, ReturnsTheSimpleValueWhenAsked)
|
||||
ASSERT_THAT(variant.get<int>(), Eq(value));
|
||||
}
|
||||
|
||||
#ifndef SDBUS_basu // Dumping message or variant to a string is not supported on basu backend
|
||||
TEST(ASimpleVariant, CanBeDumpedToAString)
|
||||
{
|
||||
const int value = 5;
|
||||
const sdbus::Variant variant(value);
|
||||
|
||||
// This should produce something like:
|
||||
// VARIANT "i" {
|
||||
// INT32 5;
|
||||
// };
|
||||
const auto str = variant.dumpToString();
|
||||
|
||||
EXPECT_THAT(str, ::HasSubstr("VARIANT \"i\""));
|
||||
EXPECT_THAT(str, ::HasSubstr("INT32"));
|
||||
EXPECT_THAT(str, ::HasSubstr("5"));
|
||||
}
|
||||
#endif // SDBUS_basu
|
||||
|
||||
TEST(AComplexVariant, ReturnsTheComplexValueWhenAsked)
|
||||
{
|
||||
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
||||
@@ -158,6 +177,39 @@ TEST(AComplexVariant, ReturnsTheComplexValueWhenAsked)
|
||||
ASSERT_THAT(variant.get<ComplexType>(), Eq(value));
|
||||
}
|
||||
|
||||
#ifndef SDBUS_basu // Dumping message or variant to a string is not supported on basu backend
|
||||
TEST(AComplexVariant, CanBeDumpedToAString)
|
||||
{
|
||||
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
||||
const ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{{"hello"s, ANY_DOUBLE}, {"world"s, ANY_DOUBLE}}} };
|
||||
const sdbus::Variant variant(value);
|
||||
|
||||
// This should produce something like:
|
||||
// VARIANT "a{ta(sd)}" {
|
||||
// ARRAY "{ta(sd)}" {
|
||||
// DICT_ENTRY "ta(sd)" {
|
||||
// UINT64 84578348354;
|
||||
// ARRAY "(sd)" {
|
||||
// STRUCT "sd" {
|
||||
// STRING "hello";
|
||||
// DOUBLE 3.14;
|
||||
// };
|
||||
// STRUCT "sd" {
|
||||
// STRING "world";
|
||||
// DOUBLE 3.14;
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
const auto str = variant.dumpToString();
|
||||
|
||||
EXPECT_THAT(str, ::HasSubstr("VARIANT \"a{ta(sd)}\""));
|
||||
EXPECT_THAT(str, ::HasSubstr("hello"));
|
||||
EXPECT_THAT(str, ::HasSubstr("world"));
|
||||
}
|
||||
#endif // SDBUS_basu
|
||||
|
||||
TEST(AVariant, HasConceptuallyNonmutableGetMethodWhichCanBeCalledXTimes)
|
||||
{
|
||||
const std::string value{"I am a string"};
|
||||
|
||||
Reference in New Issue
Block a user