ProtoBuf练习(三)
任意类型
protobuf语言的任意字段类型相当于Boost库的boost::any类型数据,google.protobuf.Any是对protobuf语言的message进行封装,所以需要使用message来封装任意类型的数据,而不能像boost::any一样直接使用基础数据类型
工程目录结构
$ ls proto/
ErrorStatus.proto
proto文件
$ cat proto/ErrorStatus.proto
syntax = "proto3";
import "google/protobuf/any.proto";
message NetworkErrorDetails
{
sint32 err_no = 1;
}
message IoErrorDetails
{
sint32 err_no = 1;
}
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}
读写源文件
$ cat reader.cpp
#include <fstream>
#include <iostream>
#include "ErrorStatus.pb.h"
using namespace std;
int main(int argc, char *argv[])
{
fstream input("./log", ios::in | ios::binary);
cout << "Deserialize start." << endl;
ErrorStatus status;
if (!status.ParseFromIstream(&input))
{
cout << "Deserialize failed." << endl;
return -1;
}
cout << status.message() << endl;
for (const google::protobuf::Any& detail : status.details())
{
// 检测Any类型具体对应的消息类型
if (detail.Is<IoErrorDetails>())
{
cout << "IoErrorStatus:" << endl;
IoErrorDetails io_error;
if (detail.UnpackTo(&io_error))
io_error.PrintDebugString();
else
cout << "Parse fails." << endl;
}
if (detail.Is<NetworkErrorDetails>())
{
cout << "NetworkErrorDetails:" << endl;
NetworkErrorDetails network_error;
if (detail.UnpackTo(&network_error))
network_error.PrintDebugString();
else
cout << "Parse fails." << endl;
}
}
cout << "Deserialize end." << endl;
input.close();
return 0;
}
$ cat writer.cpp
#include <fstream>
#include <iostream>
#include <string>
#include "ErrorStatus.pb.h"
using namespace std;
int main(int argc, char *argv[])
{
IoErrorDetails details;
details.set_err_no(1);
ErrorStatus status;
// 自动生成对象,并打包消息
status.add_details()->PackFrom(details);
status.set_message("File read operation");
fstream output("./log", ios::out | ios::trunc | ios::binary);
cout << "Serialize start." << endl;
if (!status.SerializeToOstream(&output))
{
cout << "Serialize failed." << endl;
return -1;
}
output.close();
cout << "Serialize end." << endl;
return 0;
}