DelegateMQ
Loading...
Searching...
No Matches
msgpack/Serializer.h
Go to the documentation of this file.
1#ifndef SERIALIZER_H
2#define SERIALIZER_H
3
10
11#include "msgpack.hpp"
13#include <iostream>
14#include <sstream> // Needed for dynamic_cast check
15#include <type_traits>
16#include <vector>
17
18// make_serialized serializes each remote function argument
19template<typename... Args>
20void make_serialized(msgpack::sbuffer& buffer, Args&&... args) {
21 (msgpack::pack(buffer, args), ...); // C++17 fold expression to serialize
22}
23
24template <class R>
25struct Serializer; // Not defined
26
27// Serialize all target function argument data using MessagePack library
28template<class RetType, class... Args>
29class Serializer<RetType(Args...)> : public dmq::ISerializer<RetType(Args...)>
30{
31public:
32 // Write arguments to a stream
33 virtual std::ostream& Write(std::ostream& os, Args... args) override {
34 try {
35 // Reset stream position. DelegateMQ reuses the stream instance.
36 // If we don't reset, we append new data to old data, sending [Old][New]
37 // and the receiver will always deserialize [Old].
38 os.seekp(0, std::ios::beg);
39
40 // Optimization: If it's a stringstream, clear it completely to avoid
41 // sending "tail garbage" if the new packet is smaller than the previous one.
42 // (Note: Even with garbage tail, msgpack works because it stops reading
43 // after the valid object, but clearing saves network bandwidth).
44 auto* ss = dynamic_cast<std::ostringstream*>(&os);
45 if (ss) {
46 ss->str("");
47 }
48
49 msgpack::sbuffer buffer;
50 make_serialized(buffer, args...);
51 os.write(buffer.data(), buffer.size());
52 }
53 catch (const std::exception& e) {
54 std::cerr << "Serialize error: " << e.what() << std::endl;
55 throw;
56 }
57 return os;
58 }
59
60 // Read arguments from a stream
61 virtual std::istream& Read(std::istream& is, Args&... args) override {
62 try {
63 // Read entire stream into memory buffer
64 std::vector<char> buffer_data((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
65
66 if (buffer_data.empty() && sizeof...(Args) > 0) {
67 return is;
68 }
69
70 size_t offset = 0;
71
72 // Helper lambda to unpack one argument at a time from the buffer
73 auto unpack_one = [&](auto& arg) {
74 // msgpack::unpack parses one object and updates 'offset' to point to the next byte
75 msgpack::object_handle oh = msgpack::unpack(buffer_data.data(), buffer_data.size(), offset);
76
77 // Convert msgpack object to specific C++ type
78 arg = oh.get().as<std::decay_t<decltype(arg)>>();
79 };
80
81 // Use C++17 fold expression to call unpack_one for each argument in 'args'
82 (unpack_one(args), ...);
83 }
84 catch (const msgpack::type_error& e) {
85 std::cerr << "Deserialize type conversion error: " << e.what() << std::endl;
86 throw;
87 }
88 catch (const std::exception& e) {
89 std::cerr << "Deserialize error: " << e.what() << std::endl;
90 throw;
91 }
92 return is;
93 }
94};
95
96#endif // SERIALIZER_H
Interface for custom argument serialization/deserialization.
virtual std::istream & Read(std::istream &is, Args &... args) override
Deserializes data from the input stream into function arguments.
Definition msgpack/Serializer.h:61
virtual std::ostream & Write(std::ostream &os, Args... args) override
Serializes function arguments into the output stream.
Definition msgpack/Serializer.h:33
void make_serialized(msgpack::sbuffer &buffer, Args &&... args)
Definition msgpack/Serializer.h:20
Definition bitsery/Serializer.h:27
Definition ISerializer.h:14