I has a Message define like this:
message Command{
oneof type{
Point point = 1;
Rotate rotate = 2;
Move move = 3;
... //about 100 messages
}
}
Then protoc generate the SerializeWithCachedSizes function:
void Command::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// ##protoc_insertion_point(serialize_start:coopshare.proto.Command)
::google::protobuf::uint32 cached_has_bits = 0;
(void) cached_has_bits;
// .coopshare.proto.Point point = 1;
if (has_point()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
1, *type_.point_, output);
}
// .coopshare.proto.Rotate rotate = 2;
if (has_rotate()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, *type_.rotate_, output);
}
// .coopshare.proto.Move move = 3;
if (has_move()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, *type_.move_, output);
}
The "oneof" message saves the specific type in _oneof_case_. I think using switch-case is more efficient.
But why protobuf still generate code like this?
Oneofs are internally handled similar to optional fields. In fact, descriptor.proto represents them as a set of optional fields that just have an extra oneof_index to indicate that they belong together. This is a reasonable choice, because it allowed oneofs to be used immediately with many libraries before any special support was added.
I assume that the C++ code generator uses the same structure for both optional fields and oneofs.
It is possible that switch-case could generate more efficient code, and in that case it would be useful to propose that as an improvement to the protobuf project. However, like Jorge Bellón pointed out in the comments, it is entirely possible that the compiler will be able to optimize this structure automatically. One would have to test and benchmark to be sure.
Related
I'm calling CLIPS Eval() and other functions from my C code and need help understanding how to handle return values that are CLIPSValue or UDFValue. A simple example ...
...
CLIPSValue cv;
UDFValue uv;
EvalError ee;
LoadError le;
entry->env = CreateEnvironment();
le = Load(entry->env, filePathBuffer);
if (le != LE_NO_ERROR)
{
// report the load error ...
}
// Tried this but having trouble handling cv: GetDeftemplateList(entry->env, &cv, NULL);
// Trying with Eval ...
ee = Eval(entry->env, "(list-deftemplates)", &cv);
printf("%d -- %hi -- %ld -- %s", ee, cv.multifieldValue->header.type, cv.multifieldValue->length, cv.multifieldValue->lexemeValue->contents);
...
... the above printf is broken because I'm not correctly understanding cv structure/union.
Also looking into using DataObjectToString(...) but can't see how to convert CLIPSValue to UDFValue which DataObjectToString(...) needs as input.
Further processing of the result is needed, so using something like WriteCLIPSValue(...) isn't sufficient.
Would it be possible to use a router other than STDOUT with WriteCLIPSValue(...) and similar functions to only format response strings sort of like sprintf(...)?
I'm open to whatever approach is best but prefer simple/minimal C code.
This is the code fragment for iterating over the multifield value return by GetDeftemplateList and printing the string values contained in the multifield:
GetDeftemplateList(entry->env,&cv,NULL);
for (i = 0; i < cv.multifieldValue->length; i++)
{
WriteString(mainEnv,STDOUT,cv.multifieldValue->contents[i].lexemeValue->contents);
WriteString(mainEnv,STDOUT,"\n");
}
In the most general case, you'd want to verify that cv.header->type is actually a multifield and cv.multifieldValue->contents[i].header->type is a symbol or string before pulling values out of the multifieldValue or lexemeValue unions, but in this case we know that's what GetDeftemplateList is going to return.
Is it (practically) possible to change the type name of a protobuf message type (or enum) without breaking communications?
Obviously the using code would need to be adpated to re-compile. The question is if old clients that use the same structure, but the old names, would continue to work?
Example, base on the real file:
test.proto:
syntax = "proto3";
package test;
// ...
message TestMsgA {
message TestMsgB { // should be called TestMsgZZZ going forward
// ...
enum TestMsgBEnum { // should be called TestMsgZZZEnum going forward
// ...
}
TestMsgBEnum foo = 1;
// ...
}
repeated TestMsgB bar = 1;
// ...
}
Does the on-the-wire format of the protobuf payload change in any way if type or enum names are changed?
If you're talking about the binary format, then no: names don't matter and will not impact your ability to load data; For enums, only the integer value is stored in the payload. For fields, only the field-number is stored.
Obviously if you swap two names, confusion could happen, but: it should load as long as the structure matches.
If you're talking about the JSON format, then it may matter.
I want to be able to do something like this:
for(i = 0; i < 10; i++) {
//if any button in the array is pressed, disable it.
button[i].setOnAction( ae -> { button[i].setDisable(true) } );
}
However, I get a error saying "local variables referenced from a lambda expression must be final or effectively final". How might I still do something like the code above (if it is even possible)? If it can't be done, what should be done instead to get a similar result?
As the error message says, local variables referenced from a lambda expression must be final or effectively final ("effectively final" meaning the compiler can make it final for you).
Simple workaround:
for(i = 0; i < 10; i++) {
final int ii = i;
button[i].setOnAction( ae -> { button[ii].setDisable(true) } );
}
Since you are using lambdas, you can benefit also from other features of Java 8, like streams.
For instance, IntStream:
A sequence of primitive int-valued elements supporting sequential and parallel aggregate operations. This is the int primitive specialization of Stream.
can be used to replace the for loop:
IntStream.range(0,10).forEach(i->{...});
so now you have an index that can be used to your purpose:
IntStream.range(0,10)
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Also you can generate a stream from an array:
Stream.of(button).forEach(btn->{...});
In this case you won't have an index, so as #shmosel suggests, you can use the source of the event:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->((Button)ea.getSource()).setDisable(true)));
EDIT
As #James_D suggests, there's no need of downcasting here:
Stream.of(button)
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
In both cases, you can also benefit from parallel operations:
IntStream.range(0,10).parallel()
.forEach(i->button[i].setOnAction(ea->button[i].setDisable(true)));
Stream.of(button).parallel()
.forEach(btn->btn.setOnAction(ea->btn.setDisable(true)));
Use the Event to get the source Node.
for(int i = 0; i < button.length; i++)
{
button[i].setOnAction(event ->{
((Button)event.getSource()).setDisable(true);
});
}
Lambda expressions are effectively like an annonymous method which works on stream. In order to avoid any unsafe operations, Java has made that no external variables which can be modified, can be accessed in a lambda expression.
In order to work around it,
final int index=button[i];
And use index instead of i inside your lambda expression.
You say If the button is pressed, but in your example all the buttons in the list will be disabled. Try to associate a listener to each button rather than just disable it.
For the logic, do you mean something like that :
Arrays.asList(buttons).forEach(
button -> button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
}
}));
I Also like Sedrick's answer but you have to add an action listener inside the loop .
I've run into a use case where I'd like to move an enum declared inside a protocol buffer message to outside the message so that other messages van use the same Enum.
ie, I'm wondering if there are any issues moving from this
message Message {
enum Enum {
VALUE1 = 1;
VALUE2 = 2;
}
optional Enum enum_value = 1;
}
to this
enum Enum {
VALUE1 = 1;
VALUE2 = 2;
}
message Message {
optional Enum enum_value = 1;
}
Would this cause any issues de-serializing data created with the first protocol buffer definition into the second?
It doesn't change the serialization data at all - the location / name of the enums are irrelevant for the actual data, since it just stores the integer value.
What might change is how some languages consume the enum, i.e. how they qualify it. Is it X.Y.Foo, X.Foo, or just Foo. Note that since enums follow C++ naming/scoping rules, some things (such as conflicts) aren't an issue: but it may impact some languages as consumers.
So: if you're the only consumer of the .proto, you're absolutely fine here. If you have shared the .proto with other people, it may be problematic to change it unless they are happy to update their code to match any new qualification requirements.
in short, is there a way to define a protobuf Message that contains another Message of arbitrary type? Something like:
message OuterMsg {
required int32 type = 1;
required Message nestedMsg = 2; //Any sort of message can go here
}
I suspect that there's a way to do this because in the various protobuf-implementations, compiled messages extend from a common Message base class.
Otherwise I guess I have to create a common base Message for all sorts of messages like this:
message BaseNestedMessage {
extensions 1 to max;
}
and then do
message OuterMessage {
required int32 type = 1;
required BaseNestedMessage nestedMsg = 2;
}
Is this the only way to achieve this?
The most popular way to do is to make optional fields for each message type:
message UnionMessage
{
optional MsgType1 msg1 = 1;
optional MsgType2 msg2 = 2;
optional MsgType3 msg3 = 3;
}
This technique is also described in the official Google documentation, and is well-supported across implementations:
https://developers.google.com/protocol-buffers/docs/techniques#union
Not directly, basically; protocol buffers very much wants to know the structure in advance, and the type of the message is not included on the wire. The common Message base-class is an implementation detail for providing common plumbing code - the protocol buffers specification does not include inheritance.
There are, therefore, limited options:
use different field-numbers per message-type
serialize the message separately, and include it as a bytes type, and convey the "what is this?" information separately (presumably a discriminator / enumeration)
I should also note that some implementations may provide more support for this; protobuf-net (C# / .NET) supports (separately) both inheritance and dynamic message-types (i.e. what you have above), but that is primarily intended for use only from that one library to that one library. Because this is all in addition to the specification (remaining 100% valid in terms of the wire format), it may be unnecessarily messy to interpret such data from other implementations.
Alternatively to multiple optional fields, the oneof keyword can be used since v2.6 of Protocol Buffers.
message UnionMessage {
oneof data {
string a = 1;
bytes b = 2;
int32 c = 3;
}
}