Skip to content

Commit 46058a6

Browse files
committed
Added special case for 2D arrays.
1 parent 1fd37f4 commit 46058a6

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

include/dbus-glue/bindings/message.hpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@
1111
#include <utility>
1212
#include <iostream>
1313
#include <optional>
14+
#include <functional>
1415

1516
namespace DBusGlue
1617
{
18+
struct custom_value
19+
{
20+
std::function<int(message&)> read;
21+
std::function<int(message&)> write;
22+
};
23+
1724
class message
1825
{
1926
public:
@@ -256,6 +263,15 @@ namespace DBusGlue
256263
// read_proxy
257264
//-----------------------------------------------------------------------------------------------------------------
258265

266+
template <>
267+
struct message::read_proxy<custom_value, void>
268+
{
269+
static int read(message& msg, custom_value& reader)
270+
{
271+
return reader.read(msg);
272+
}
273+
};
274+
259275
template <
260276
template <typename, typename...>
261277
typename ContainerT,
@@ -302,6 +318,78 @@ namespace DBusGlue
302318
}
303319
};
304320

321+
template <
322+
template <typename, typename...>
323+
typename ContainerOuterT,
324+
template <typename>
325+
typename AllocatorOuterT,
326+
template <typename, typename...>
327+
typename ContainerInnerT,
328+
template <typename>
329+
typename AllocatorInnerT,
330+
typename ValueT>
331+
struct message::read_proxy<
332+
ContainerOuterT<
333+
ContainerInnerT<ValueT, AllocatorInnerT<ValueT>>,
334+
AllocatorOuterT<ContainerInnerT<ValueT, AllocatorInnerT<ValueT>>>>,
335+
void>
336+
{
337+
using container_inner_type = ContainerInnerT<ValueT, AllocatorInnerT<ValueT>>;
338+
using container_type = ContainerOuterT<container_inner_type, AllocatorOuterT<container_inner_type>>;
339+
static int read(message& msg, container_type& container)
340+
{
341+
using namespace std::string_literals;
342+
343+
sd_bus_message* smsg = static_cast<sd_bus_message*>(msg);
344+
auto type = msg.type();
345+
346+
if (type.type != 'a')
347+
throw std::invalid_argument("contained type is not an array ("s + type.string() + ")");
348+
349+
auto r = sd_bus_message_enter_container(smsg, SD_BUS_TYPE_ARRAY, type.contained.data());
350+
if (r < 0)
351+
throw std::runtime_error("could not enter array: "s + strerror(-r));
352+
353+
auto reduced = type.contained.substr(1);
354+
355+
container.clear();
356+
r = 1;
357+
int r2 = 1;
358+
while (r > 0)
359+
{
360+
r2 = sd_bus_message_enter_container(smsg, SD_BUS_TYPE_ARRAY, reduced.data());
361+
if (r2 <= 0)
362+
break;
363+
364+
container_inner_type inner{};
365+
while (r2 > 0)
366+
{
367+
ValueT v;
368+
r2 = msg.read(v);
369+
if (r2 < 0)
370+
{
371+
sd_bus_message_exit_container(smsg);
372+
throw std::runtime_error("could not read from array: "s + strerror(-r));
373+
}
374+
else if (r2 > 0)
375+
inner.push_back(v);
376+
}
377+
378+
r = sd_bus_message_exit_container(smsg);
379+
if (r < 0)
380+
throw std::runtime_error("could not exit array: "s + strerror(-r));
381+
382+
container.push_back(inner);
383+
}
384+
385+
r = sd_bus_message_exit_container(smsg);
386+
if (r < 0)
387+
throw std::runtime_error("could not exit array: "s + strerror(-r));
388+
389+
return r;
390+
}
391+
};
392+
305393
template <>
306394
struct message::read_proxy<std::string, void>
307395
{
@@ -563,6 +651,15 @@ namespace DBusGlue
563651
// append_proxy
564652
//-----------------------------------------------------------------------------------------------------------------
565653

654+
template <>
655+
struct message::append_proxy<custom_value, void>
656+
{
657+
static int write(message& msg, custom_value const& writer)
658+
{
659+
return writer.write(msg);
660+
}
661+
};
662+
566663
template <>
567664
struct message::append_proxy<std::string, void>
568665
{

0 commit comments

Comments
 (0)