Created
April 21, 2015 21:39
-
-
Save mvirkkunen/0539294fd15a8234df4e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 ∈ | |
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