Make Serialize accept argument SerializeFormat format

Rename `const char* GetString()` to GetCString and add `std::string GetString()`
WIP on serializers/msgpack.h
This commit is contained in:
Fangrui Song 2018-01-06 18:01:32 -08:00
parent 76a3fe8400
commit 5809d0c436
9 changed files with 110 additions and 64 deletions

View File

@ -31,7 +31,7 @@ struct RealCacheManager : ICacheManager {
WriteToFile(cache_path, file.file_contents_); WriteToFile(cache_path, file.file_contents_);
} }
std::string indexed_content = Serialize(file); std::string indexed_content = Serialize(config_->cacheFormat, file);
WriteToFile(AppendSerializationFormat(cache_path), indexed_content); WriteToFile(AppendSerializationFormat(cache_path), indexed_content);
} }

View File

@ -479,7 +479,7 @@ IndexVar* IndexFile::Resolve(IndexVarId id) {
} }
std::string IndexFile::ToString() { std::string IndexFile::ToString() {
return Serialize(*this); return Serialize(SerializeFormat::Json, *this);
} }
IndexType::IndexType(IndexTypeId id, const std::string& usr) IndexType::IndexType(IndexTypeId id, const std::string& usr)

View File

@ -154,7 +154,7 @@ inline bool operator!=(const IndexFuncRef& a, const IndexFuncRef& b) {
} }
inline void Reflect(Reader& visitor, IndexFuncRef& value) { inline void Reflect(Reader& visitor, IndexFuncRef& value) {
const char* str_value = visitor.GetString(); const char* str_value = visitor.GetCString();
if (str_value[0] == '~') { if (str_value[0] == '~') {
value.is_implicit = true; value.is_implicit = true;
++str_value; ++str_value;

View File

@ -149,7 +149,7 @@ void Reflect(Reader& visitor, Position& value) {
if (!visitor.IsString()) if (!visitor.IsString())
value = Position(); value = Position();
else else
value = Position(visitor.GetString()); value = Position(visitor.GetCString());
} }
void Reflect(Writer& visitor, Position& value) { void Reflect(Writer& visitor, Position& value) {
std::string output = value.ToString(); std::string output = value.ToString();
@ -161,7 +161,7 @@ void Reflect(Reader& visitor, Range& value) {
if (!visitor.IsString()) if (!visitor.IsString())
value = Range(); value = Range();
else else
value = Range(visitor.GetString()); value = Range(visitor.GetCString());
} }
void Reflect(Writer& visitor, Range& value) { void Reflect(Writer& visitor, Range& value) {
std::string output = value.ToString(); std::string output = value.ToString();

View File

@ -1,6 +1,5 @@
#include "serializer.h" #include "serializer.h"
// TODO Move Json* to serializers/json.cc
#include "serializers/json.h" #include "serializers/json.h"
#include "serializers/msgpack.h" #include "serializers/msgpack.h"
@ -192,44 +191,65 @@ void Reflect(TVisitor& visitor, IndexFile& value) {
REFLECT_MEMBER_END(); REFLECT_MEMBER_END();
} }
std::string Serialize(IndexFile& file) { std::string Serialize(SerializeFormat format, IndexFile& file) {
rapidjson::StringBuffer output;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(output);
writer.SetFormatOptions(
rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
writer.SetIndent(' ', 2);
JsonWriter json_writer(&writer); switch (format) {
Reflect(json_writer, file); case SerializeFormat::Json: {
rapidjson::StringBuffer output;
return output.GetString(); rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(output);
writer.SetFormatOptions(
rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
writer.SetIndent(' ', 2);
JsonWriter json_writer(&writer);
Reflect(json_writer, file);
return output.GetString();
}
case SerializeFormat::MessagePack: {
msgpack::sbuffer buf;
msgpack::packer<msgpack::sbuffer> pk(&buf);
MessagePackWriter msgpack_writer(&pk);
Reflect(msgpack_writer, file);
return std::string(buf.data(), buf.size());
}
}
return "";
} }
std::unique_ptr<IndexFile> Deserialize(SerializeFormat format, std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
std::string path, std::string path,
std::string serialized, std::string serialized,
optional<int> expected_version) { optional<int> expected_version) {
rapidjson::Document reader; std::unique_ptr<IndexFile> file;
reader.Parse(serialized.c_str()); switch (format) {
if (reader.HasParseError()) case SerializeFormat::Json: {
return nullptr; rapidjson::Document reader;
reader.Parse(serialized.c_str());
if (reader.HasParseError())
return nullptr;
// Do not deserialize a document with a bad version. Doing so could cause a // Do not deserialize a document with a bad version. Doing so could cause a
// crash because the file format may have changed. // crash because the file format may have changed.
if (expected_version) { if (expected_version) {
auto actual_version = reader.FindMember("version"); auto actual_version = reader.FindMember("version");
if (actual_version == reader.MemberEnd() || if (actual_version == reader.MemberEnd() ||
actual_version->value.GetInt() != expected_version) { actual_version->value.GetInt() != expected_version) {
return nullptr; return nullptr;
}
}
file = MakeUnique<IndexFile>(path);
JsonReader json_reader{&reader};
Reflect(json_reader, *file);
break;
}
case SerializeFormat::MessagePack: {
msgpack::object_handle oh = msgpack::unpack(serialized.data(), serialized.size());
(void)oh;
break;
} }
} }
// TODO msgpack
(void)format;
auto file = MakeUnique<IndexFile>(path);
JsonReader json_reader{&reader};
Reflect(json_reader, *file);
// Restore non-serialized state. // Restore non-serialized state.
file->path = path; file->path = path;
file->id_cache.primary_file = file->path; file->id_cache.primary_file = file->path;

View File

@ -27,7 +27,8 @@ class Reader {
virtual int GetInt() = 0; virtual int GetInt() = 0;
virtual int64_t GetInt64() = 0; virtual int64_t GetInt64() = 0;
virtual uint64_t GetUint64() = 0; virtual uint64_t GetUint64() = 0;
virtual const char* GetString() = 0; virtual const char* GetCString() = 0;
virtual std::string GetString() { return GetCString(); }
virtual bool HasMember(const char* x) = 0; virtual bool HasMember(const char* x) = 0;
virtual std::unique_ptr<Reader> operator[](const char* x) = 0; virtual std::unique_ptr<Reader> operator[](const char* x) = 0;
@ -245,7 +246,7 @@ void ReflectMember(Reader& visitor, const char* name, T& value) {
visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); }); visitor.DoMember(name, [&](Reader& child) { Reflect(child, value); });
} }
std::string Serialize(IndexFile& file); std::string Serialize(SerializeFormat format, IndexFile& file);
std::unique_ptr<IndexFile> Deserialize(SerializeFormat format, std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
std::string path, std::string path,
std::string serialized, std::string serialized,

View File

@ -24,7 +24,7 @@ class JsonReader : public Reader {
int GetInt() override { return m_->GetInt(); } int GetInt() override { return m_->GetInt(); }
int64_t GetInt64() override { return m_->GetInt64(); } int64_t GetInt64() override { return m_->GetInt64(); }
uint64_t GetUint64() override { return m_->GetUint64(); } uint64_t GetUint64() override { return m_->GetUint64(); }
const char* GetString() override { return m_->GetString(); } const char* GetCString() override { return m_->GetString(); }
bool HasMember(const char* x) override { return m_->HasMember(x); } bool HasMember(const char* x) override { return m_->HasMember(x); }
std::unique_ptr<Reader> operator[](const char* x) override { std::unique_ptr<Reader> operator[](const char* x) override {

View File

@ -5,37 +5,61 @@
#include <msgpack.hpp> #include <msgpack.hpp>
class MessagePackReader : public Reader { class MessagePackReader : public Reader {
msgpack::object_handle* m_; msgpack::unpacker* m_;
msgpack::object_handle oh_;
void next() { m_->next(oh_); }
public: public:
MessagePackReader(msgpack::object_handle* m) : m_(m) {} MessagePackReader(msgpack::unpacker* m) : m_(m) { next(); }
SerializeFormat Format() const override { return SerializeFormat::MessagePack; }
//bool GetBool() override { return m_->GetBool(); } bool IsNull() override { return oh_.get().is_nil(); }
//int GetInt() override { return m_->GetInt(); } bool IsArray() override { return oh_.get().type == msgpack::type::ARRAY; }
//int64_t GetInt64() override { return m_->GetInt64(); } bool IsInt() override {
//uint64_t GetUint64() override { return m_->GetUint64(); } return oh_.get().type == msgpack::type::POSITIVE_INTEGER ||
//const char* GetString() override { return m_->GetString(); } oh_.get().type == msgpack::type::NEGATIVE_INTEGER;
}
bool IsString() override { return oh_.get().type == msgpack::type::STR; }
//bool HasMember(const char* x) override { return m_->HasMember(x); } bool GetBool() override {
//std::unique_ptr<Reader> operator[](const char* x) override { auto ret = oh_.get().as<bool>();
// auto& sub = (*m_)[x]; next();
// return std::unique_ptr<JsonReader>(new JsonReader(&sub)); return ret;
//} }
int GetInt() override {
auto ret = oh_.get().as<int>();
next();
return ret;
}
int64_t GetInt64() override {
auto ret = oh_.get().as<int64_t>();
next();
return ret;
}
uint64_t GetUint64() override {
auto ret = oh_.get().as<uint64_t>();
next();
return ret;
}
const char* GetCString() override {
auto ret = oh_.get().as<char*>();
next();
return ret;
}
//void IterArray(std::function<void(Reader&)> fn) override { bool HasMember(const char* x) override { return true; }
// for (auto& entry : m_->GetArray()) { std::unique_ptr<Reader> operator[](const char* x) override {
// MessagePackReader sub(&entry); return {};
// fn(sub); }
// }
//}
//void DoMember(const char* name, std::function<void(Reader&)> fn) override { void IterArray(std::function<void(Reader&)> fn) override {
// auto it = m_->FindMember(name); }
// if (it != m_->MemberEnd()) {
// MessagePackReader sub(&it->value); void DoMember(const char* name, std::function<void(Reader&)> fn) override {
// fn(sub); const char* key = GetCString();
// } fn(*this);
//} }
}; };
class MessagePackWriter : public Writer { class MessagePackWriter : public Writer {
@ -43,6 +67,7 @@ class MessagePackWriter : public Writer {
public: public:
MessagePackWriter(msgpack::packer<msgpack::sbuffer>* m) : m_(m) {} MessagePackWriter(msgpack::packer<msgpack::sbuffer>* m) : m_(m) {}
SerializeFormat Format() const override { return SerializeFormat::MessagePack; }
void Null() override { m_->pack_nil(); } void Null() override { m_->pack_nil(); }
void Bool(bool x) override { m_->pack(x); } void Bool(bool x) override { m_->pack(x); }

View File

@ -75,9 +75,9 @@ void DiffDocuments(std::string path,
void VerifySerializeToFrom(IndexFile* file) { void VerifySerializeToFrom(IndexFile* file) {
std::string expected = file->ToString(); std::string expected = file->ToString();
std::unique_ptr<IndexFile> result = std::unique_ptr<IndexFile> result = Deserialize(
Deserialize(SerializeFormat::Json, "--.cc", Serialize(*file), SerializeFormat::Json, "--.cc", Serialize(SerializeFormat::Json, *file),
nullopt /*expected_version*/); nullopt /*expected_version*/);
std::string actual = result->ToString(); std::string actual = result->ToString();
if (expected != actual) { if (expected != actual) {
std::cerr << "Serialization failure" << std::endl; std::cerr << "Serialization failure" << std::endl;