Skip to content

Instantly share code, notes, and snippets.

@mvirkkunen
Created April 21, 2015 21:39
Show Gist options
  • Save mvirkkunen/0539294fd15a8234df4e to your computer and use it in GitHub Desktop.
Save mvirkkunen/0539294fd15a8234df4e to your computer and use it in GitHub Desktop.
#include <cstdint>
#include <initializer_list>
#include <iostream>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>
class Serializer {
private:
int field_index = -1;
std::ostream &out;
void write(int32_t &value) {
out << value << " ";
}
void write(std::string &value) {
out << value << " ";
}
template <typename TValue>
void write(std::vector<TValue> &value) {
out << value.size() << " ";
for (size_t i = 0; i < value.size(); i++)
write(value[i]);
}
template <typename TEnum>
typename std::enable_if<std::is_enum<TEnum>::value>::type write(TEnum &value) {
out << (int32_t)value << " ";
}
template <typename TValue>
typename std::enable_if<!std::is_enum<TValue>::value>::type write(TValue &value) {
field_index = -1;
value.fields(*this);
out << 0 << " ";
}
public:
Serializer(std::ostream &out) : out(out) { }
template <typename TValue>
inline void field(int index, TValue &value) {
out << index << " ";
write(value);
}
template <typename TValue>
void serialize(TValue &value) {
write(value);
}
};
class Deserializer {
private:
int field_index = -1;
std::istream &in;
void read(int32_t &value) {
in >> value;
}
void read(std::string &value) {
in >> value;
}
template <typename TValue>
void read(std::vector<TValue> &value) {
size_t size;
in >> size;
for (size_t i = 0; i < size; i++) {
value.emplace_back();
read(value[i]);
}
}
template <typename TValue>
typename std::enable_if<std::is_enum<TValue>::value>::type read(TValue &value) {
int32_t i;
in >> i;
value = (TValue)i;
}
template <typename TValue>
typename std::enable_if<!std::is_enum<TValue>::value>::type read(TValue &value) {
while (true) {
int index;
in >> index;
if (index == 0)
break;
field_index = index;
value.fields(*this);
}
}
public:
Deserializer(std::istream &in) : in(in) { }
template <typename TValue>
inline void field(int index, TValue &value) {
if (index == field_index)
read(value);
}
template <typename TValue>
void deserialize(TValue &value) {
read(value);
}
};
// enum
// struct
// union
// bool byte i16 i32 i64 double string binary
// map set list
// ----------
class Attribute {
public:
std::string key;
std::string value;
template<typename T> void fields(T &s) {
s.field(1, key);
s.field(2, value);
}
};
enum class MessageType : int32_t {
TEXT = 1,
IMAGE = 2,
};
class Message {
public:
int32_t id;
MessageType type;
std::string content;
std::vector<Attribute> attrs;
void dump() {
std::cout << "id=" << id << "\n"
<< "content=" << content << "\n"
<< "type=" << (int32_t)type << "\n"
<< "attrs=\n";
for (size_t i = 0; i < attrs.size(); i++) {
std::cout << " key=" << attrs[i].key << "\n"
<< " value=" << attrs[i].value << "\n";
}
}
template<typename T> void fields(T &s) {
s.field(1, id);
s.field(2, content);
s.field(3, attrs);
s.field(4, type);
}
};
// ----------
int main() {
Message msg;
msg.id = 123;
msg.type = MessageType::IMAGE;
msg.content = "hello";
Attribute attr;
attr.key = "K";
attr.value = "V";
msg.attrs.push_back(attr);
msg.dump();
std::stringstream ss;
Serializer(ss).serialize(msg);
ss.seekg(0);
Message msg_back;
Deserializer(ss).deserialize(msg_back);
msg_back.dump();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment