Protocol buffer split oneof message to a different file - protocol-buffers

I use nanopb and a .proto file that looks like this (simplified):
syntax = "proto3";
message Type1
{
bool a = 1;
}
message Type2
{
int32 b = 1;
}
message Message
{
int32 id = 1;
oneof oneMessage {
Type1 messageType1 = 2;
Type2 messageType2 = 3;
}
}
I now need to split the oneMessage to a different .proto file and import it. I can do something like:
file a.proto:
syntax = "proto3";
import "b.proto"
message Message
{
int32 id = 1;
oneofTypeMessage aMessage = 2;
}
file b.proto
syntax = "proto3";
message Type1
{
bool a = 1;
}
message Type2
{
int32 b = 1;
}
message oneofTypeMessage
{
oneof oneMessage {
Type1 messageType1 = 2;
Type2 messageType2 = 3;
}
}
But this means I can't get to my message types with message.messageType1, triggering lots of changes in the existing source code. How can I split the oneof part to another file without changing the way I access to it?
I've tried declaring Message in both files but it is not permitted.

No. oneMessage is not a message type, and to import something from another file, it must be a message type. Adding a new oneofTypeMessage would add an additional node in the graph, and would not be data-compatible with the original data.
You can move Type1 and Type2, but the oneof must stay as-was; so: this is valid:
file a.proto:
syntax = "proto3";
import "b.proto"
message Message
{
int32 id = 1;
oneof oneMessage {
Type1 messageType1 = 2;
Type2 messageType2 = 3;
}
}
file b.proto:
syntax = "proto3";
message Type1
{
bool a = 1;
}
message Type2
{
int32 b = 1;
}

Related

Parse nested (opaque, any-typed) Protobuf message

I have a message envelope:
import "google/protobuf/any.proto";
message Envelope {
string type = 1;
int32 version = 2;
string message_id = 5;
string timestamp = 6;
google.protobuf.Any message = 7;
}
Now, I happen to know that the message is another Protobuf value with the following type:
And a message defined as follows:
message Message {
int32 value = 1;
string name = 2;
}
Is it possible for me to do a one-shot parsing of this combined message? I am thinking that the problem with substituting Any with Message is the field numbering.
Any is just:
message Any {
string type_url = 1;
bytes value = 2;
}
where the value is just the regular payload content. If you know that the type is your Message, then you can use instead
message Envelope {
string type = 1;
int32 version = 2;
string message_id = 5;
string timestamp = 6;
FakeAny message = 7;
}
message FakeAny {
// don't even need to capture the type_url
Message value = 2;
}
message Message {
int32 value = 1;
string name = 2;
}
and it should deserialize directly.

Reusing Message in the same package in multiple files

Is there a way to reuse protobuf structs across multiple proto files?
in the client.proto file I have the following
message SingleOperation {
string command = 1;
}
message ClientBatch {
string unique_id = 1;
repeated SingleOperation requests = 2;
int64 sender = 3;
}
Then in network.proto file, I have the following
message MemPool {
int32 sender = 1;
string unique_id = 2;
SingleOperation op = 3;
}
In the network.proto file, I need to reuse the SingleOperation message.
However, I do not see an option to do this.
Does protobuff support some sort of packaging to support struct reuse?

How to represent a mix of enum and oneof in protobuf

I am trying to create a protocol buffer message with fields that are either a message or one of a choice of some constant (like an enum). Something that is logically equivalent to:
message Error {
oneof error_type {
EMPTY_METHOD_NAME = 0
ExecutionError execution_error = 1;
}
message ExecutionError {
string value = 1;
}
}
Essentially, I would like a field that can represent either an error type that is just a name with no fields, or an error type that has fields. How would I do this with protobuf3?
See Enumerations in the Language Guide (proto3)
message Error {
oneof error_type {
Foo foo = 1;
ExecutionError execution_error = 2;
}
enum Foo {
X = 0;
Y = 1;
Z = 2;
}
message ExecutionError {
string value = 1;
}
}

oneof CustomType protobuf

I am tyring to replicate python schema code to golang(protobuf). I am stuck in 1 of the condition.
message Type1 {
enum Type{
type1 = 1
}
Type type = 0;
string name = 1;
}
message Type2 {
enum Type{
type2 = 1
}
Type type = 0;
string name = 1;
repeated string value = 2;
}
message Type3 {
enum Type{
time = 1
}
Type type = 0;
string name = 1;
string format = 2;
string value = 3;
}
message Request {
something
something
map<string, oneof_above_defined_types> params = n
}
How do i make sure that map takes only custom types defined above?
I think you'll need to define a new type that includes the oneof type:
message TypeX {
oneof type_oneof {
Type1 type_1 = 1;
Type2 type_2 = 2;
Type3 type_3 = 3;
};
}
message Request {
...
map<string, TypeX> params = n;
}

In a proto, how can I define a map as a custom option

In my proto file, I want to define a map as a custom option, tried a few things but none is working.
my metadata proto file:
syntax = "proto2";
import "google/protobuf/descriptor.proto";
package com.util;
option java_package = "com.util";
message MyMeta {
optional bool needValidation = 1;
map<string, string> fileMap = 2;
}
extend google.protobuf.FieldOptions {
optional MyMeta meta = 80412;
}
my proto file
syntax = "proto3";
package com.test;
import "util/meta.proto";
import "google/protobuf/timestamp.proto";
message MyMeta {
int32 id = 1 [(com.util.meta).needValidation = false, /*looking for a way to set a map (com.meta).tableOptions = {"t,raw_orders"}]*/;
}
Is this possible?
This works:
message MyMeta {
int32 id = 1 [
(com.util.meta) = {
needValidation: false,
fileMap: [
{
key: "t",
value: "raw_orders"
}
];
}];
}
The protobuf map is syntactic sugar for a repeated field of map entry messages with key and value fields. 1
In your case, your meta message
message MyMeta {
optional bool needValidation = 1;
map<string, string> fileMap = 2;
}
is equivalent to
message MyMeta {
optional bool needValidation = 1;
message FileMapEntry {
string key = 1;
string value = 2;
}
repeated FileMapEntry fileMap = 2;
}
Of course, it would be much nicer if there was a more obvious way to specify a map value in an option.
Seems it is not possible. To make my logic, I created a string like "StoreOrders:raw_orders_test,OrderItems:raw_order_items_test
message MyMeta {
int32 id = 1 [(com.util.meta).needValidation = false, (com.meta).tableOptions = "TableA:valueA,TableB:valueB;
}
and in my jav code and splitting the string to create a hash map.

Resources