Explicitly serialize Slice object to string or ostream in C++ - c++

Is there a way to explicitly serialize a Slice object to a string using ice? The problem is that there is an object which must be sendable by json / xml / ice and since ice already has a platform independent object in the Specification Language for Ice(Slice), there is no need to include another library like protobuf. But as far as I can see, it is not possible to serialize the object explicitly. Am I wrong?

You can serialize the object in the Ice binary format using the OutputStream API
Ice::ByteSeq inParams, outParams;
Ice::OutputStream out(communicator);
out.startEncapsulation();
Demo::CPtr c = new Demo::C;
c->s.name = "blue";
c->s.value = Demo::blue;
out.write(c);
out.writePendingValues();
out.endEncapsulation();
out.finished(inParams);
There is additional examples in ice-demos repository https://github.com/zeroc-ice/ice-demos/tree/3.7/cpp98/Ice/invoke
The docs for OutputStream can be found at https://doc.zeroc.com/ice/3.7/client-server-features/dynamic-ice/streaming-interfaces/c++-streaming-interfaces/the-outputstream-interface-in-c++

Related

Mocking proto.Message in Go

I wrote a function that takes a list of proto.Message objects. Looking at the documentation, it seems like proto.Message wraps protoreflect.ProtoMessage which contains a single function, ProtoReflect() Message. Looking at the documentation for Message, it implements a number of other functions that return types referenced by the protoreflect package.
It seems that attempting to create a mock proto.Message would be a lot more work that it's worth but I don't want to go through the whole process of creating a protobuf file, compiling it and referencing it just for unit testing.
Is there another way I can create a mock proto.Message object?
After looking into this further, I decided that the best thing to do would be to create an actual protobuf message:
syntax = "proto3";
package my.package;
option go_package = "path/to/my/package"; // golang
message TestRecord {
string key = 1;
string value = 2;
}
and compile it into a Golang file and then modify it for my own purposes:
$ protoc --go_out=./gopb/ --go_opt=paths=source_relative *.proto
Once the test file has been created, I can delete it or save it as a record.

Serialize C++ classes between processes and across the network

I'd like to understand how to transmit the contents of a C++ class between processes or across a network.
I'm reading the Google Protobuf tutorial:
https://developers.google.com/protocol-buffers/docs/cpptutorial
and it seems you must create an abstracted, non-C++ interface to represent your class:
syntax = "proto2";
package tutorial;
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
}
However, I'd prefer to specify my class via C++ code (rather than the abstraction) and just add something like serialize() and deserialize() methods.
Is this possible with Google Protobuf? Or is this how Protobuf works and I'd need to use a different serialization technique?
UPDATE
The reason for this is I don't want to have to maintain two interfaces. I'd prefer to have one C++ class, update it and not have to worry about a second .proto interface/definition. Code maintainability.
That's how Protobuf works. You have to use something else if you want to serialize your manually-written C++ classes. However, I'm not sure you really want that, because you then will have to either restrict yourself to very simple fields with no invariants (just like in Protobuf) or write custom (de)serialization logic yourself.
You could make a simple protocol buffer to hold binary information, but it sort of breaks the point of using Protocol buffers.
You can sort of cheat the system by using SerializeToString() and ParseFromString() to simply serialize binary information into a string.
There is also SerializeToOstream() and ParseFromIstream().
The real value of protocol buffers is being able to use messages across programs, systems and languages while using a single definition. If you aren't making messages using the protocol they've defined; this is more work than simply using native C++ capabilities.

Can we invoke self-defined callback function in the parser of google protocol buffer textformat?

In google protocol buffer, there exists a textual version of message. When parsing this textual message, can we define ourselves the callback functions in order that we could store the information parsed into our own data structure?
For example, if we have defined .proto:
message A {
required string name = 1;
optional string value =2;
repeated B bList =3;
}
message B {
required string name =1;
optional string value =2;
}
And we have textformat message:
A {
name: "x"
value: "123"
B {
name: "y"
value: "987"
}
B {
name: "z"
value: "965"
}
}
The protobuf compiler generates the corresponding class named "A", class named "B". The parser can parse this text format into the instance of A. However, if user want to defined our own version of class "A", or there exists a version of A used before. Now as we would like to replace the old exchange format by google protocol buffer, we are willing to parse the google protocol buffer text format version directly into the old data structure. If not, we will have to first of all have the generated data structure (class "A") filled then adapt the generated data structure to the legacy data structure. It occupies two times the memory than necessary. It can be much less efficient than we wanted.
The traditional method used for integrating a parser is to have a parser that can callback self-defined functors to be accustomed to the new data structure.
So, does there exist a way to inject the self-defined callback function into the text format parser?
No, the protobuf TextFormat implementation does not support such extensions.
That said, TextFormat (in at least C++, Java, and Python) is implemented as a self-contained module that operates only on public interfaces (mainly, the reflection interface). You can easily clone it and then make your own modifications to the format, or even write a whole new module in the same style that implements any arbitrary format. For example, many people have written JSON parsers / encoders based on Protobuf reflection, using the TextFormat implementation as a guide.

design pattern for "save"

I'm currently working on a "save" mechanism, which allows a user to save the project his working on on hard disc. The output will be a XML file containing all kinds of data.
Now our project structure is about to change and we need to write a new xml file (create a new save method).
So now here comes the challenge: When saving I want the user to be able to choose which file format he will be creating (version1 (old) or version2 (new)).
Does anyone now how to achieve that? Is there a suitable design pattern around?
Remarks:
- The data we are saving can be seen as unrelated blocks, so it would actually be easy to exchange an old block with a new one.
- The whole goal of the thing is, it should be readable again when loading an old project. (I assume this can be done by tags, and just react on tags when loading?)
This sounds like a good application for the Strategy pattern.
You would create an abstract base class FileFormat (the Strategy interface) with two virtual functions, projectToXml and xmlToProject, which are supposed to turn your internal project representation into XML or vice versa.
Then you create two implementing subclasses FileFormatNew and FileFormatLegacy (these are the concrete strategies).
Your save functions would then additionally require an instance of FileFormat, and call the corresponding method of that object to do the data conversion. Your load function could choose the strategy to use by examining the XML tree for something which tells it which version it is.
And when you ever need to support another file format, you just have to create a new class which is a subclass of FileFormat.
Addendum after the exchange in the comments
When you are going to have a lot of versions with very small differences and you still want to use the Strategy pattern, you could make the FileFormat a composite of multiple strategies: A CircleStragegy, a RectangleStrategy, a LineStrategy etc.. In that case I wouldn't use different classes for different versions of the FileFormat. I would create a static factory function for each version which returns a FileFormat with the Strategy objects used in that version.
FileFormat FileFormat::createVersion1_0() {
return new FileFormat(
new LineStrategyOld(),
new CircleStrategyOld(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_1() {
// the 1.1 version introduced the new way to save lines
return new FileFormat(
new LineStrategyNew(),
new CircleStrategyOld(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_2() {
// 1.2 uses the new format to save circles
return new FileFormat(
new LineStrategyNew(),
new CircleStrategyNew(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_3() {
// 1.3 uses a new format to save rectangles, but we realized that
// the new way to save lines wasn't that good after all, so we
// returned to the old way.
return new FileFormat(
new LineStrategyOld(),
new CircleStrategyNew(),
new RectangleStragegyNew()
);
}
Note: In real code you would of course use more descriptive suffixes than "Old" and "New" for your strategy class names.

Can I serialize/deserialize JSON from protocol buffers with C++?

There are frameworks for Java and other languages that help connect protocol buffers to JSON, but I have not seen a native solution in C++.
Is there a library/framework that I can use to connect C++ protocol buffer objects to JSON?
I'm developing one. I'm using the protobuf's reflection mechanism to parse any generated protobuf. Here http://corbasim.googlecode.com/svn/trunk/protobuf2json_exported.zip you can find an initial implementation of this idea. It currently just parse string fields, but I want to support any type as soon as possible.
For a message Foo:
message Foo {
optional string text = 1;
}
it can parse instances of Foo by this way:
Foo foo;
const std::string json_foo = "{\"text\": \"Hello world\"}";
protobuf2json::json::parse(foo, json_foo)
By the same way, I want to write a JSON serializer from protobuf generated types.
There is a similar question here:
C++ Protobuf to/from JSON conversion
pb2json is another library that can be used.