convert protobuf to other protobuf - protobuf-java

I have reading Protobuf from Kaka so finally I'm getting a generated Java Object.
I would like to rename/create other Protobuf based on the original I got.
let say I have 2 classes A and B.
my code listen to Kafka topic and gets A.
I would like to "convert" A to B which is almost the same Object (few variable name changes).
is there any way to overwrite Protobuf Parser? in order to Generate B instead of A?
for example:
Class A{
String aa;
int aaaa;
}
Class B{
String bb;
int bbbb;
}
my Listener gets A and i would like to get B (bb=aa, bb=aaaa

Assuming A and B are compatible (same tags have the same type), you can serialize back your proto and parse it again.
This will also work if some tags are missing in one object, but parsing will mostly fail if two tags exists with the different types.
Proto:
Message A {
string aa = 1;
int32 aaaa = 2;
int32 a_only = 3;
}
Message B {
string bb = 1;
int32 bbbb = 2;
string b_only = 4; // Must not be 3.
}
Java:
A a = GetAFromQueue();
B b = B.parseFrom(a.toByteArray());
Another (probably better) option would be to get a the message from Kafka as a byte array and to parse it into a A or into a B as needed. This avoids re-serializing the data, though the same tags with different type issue is still relevant.
byte[] data = GetDataFromQueue();
A a = A.parseFrom(data);
[...]
B b = B.parseFrom(data);

Related

Issue in proto3 file format data type error

I am working on project where I am using nodejs and Proto3 for jobs. I have following proto3 file. where I want to add version as a field.
message Request {
string id = 1;
string body = 4;
string createdAt = 5;
string updatedAt = 6;
string traceId = 7;
}
I have an additional field version, when I was sending this field to it my system was giving error
Expect string provided number
So I modified it like this
message Request {
string id = 1;
string body = 4;
string createdAt = 5;
string updatedAt = 6;
string traceId = 7;
optional int32 version = 8;
}
Now I am getting reverse error that it expected integer and getting string. Althought I define here int32 which is integer in proto3.
I think it is about matching number in nodejs and int32 in proto3. I tried optional float version = 8; but still getting.
Here is complete error.
message="[rabbit] Request received"
version_$numberLong="1"
request.version: number expected" stack="Error: request.version: number expected\n
It is saying it expect number and client is sending number version_$numberLong="1". The project is a lot complicated with large files I just condense to show working code. Any solution how can I make them to work together.

How to define a *.proto file with variable payload length?

I try to write my first *.proto file. This is my try:
syntax = "proto3";
package Message;
message Message {
string name = 1;
string serial = 2;
int32 command = 3;
enum Status {
GOOD = 0;
BAD = 1;
}
Status status = 4;
int32 length = 5;
// end of header
// start of payload
int32 data = 6;
string address = 7;
}
The header has the field length. This value defines the length of the data field in the payload. And that is my problem: The data field is dynamic, I can't know the size right now.
I could split the header and the payload in 2 separate *.proto files. But then still I don't know how to dynamically set the length of one of the fields.
Thanks in advance for the help!
Protocol buffer does not allow to check dependencies between fields. You have to check if the length matches the length of data yourself.

Cannot perform boxing using as keyword for a string reference type in C#

Boxing Conversion can be acheived by using as keyword
So I tried to perform boxing using as keyword.
So I tried the below example
Eg 1:-
int i = 12;
string a = i.ToString(); // Boxing Conversion
Console.WriteLine(a); //This works
Console.ReadKey();
Eg 2:-
var aa = i as object; // This works
var a = (i as string) // Compile time error
var a = (i as string).ToString(); // Compile time error
Can anyone explain why boxing can't be performed using as keyword for a string reference type?
1)
int i = 12;
string a = i.ToString();
ToString() is not a boxing conversion at all (and I'm not sure the term is quite right - boxing is just boxing). It is conversion to string. "a" is totally different object, not related to i anymore. It's type is string and value is "12", not 12.
2)
int i = 12;
var aa = i as object;
It is boxing, but aa still keeps object of int type.
var a = (i as string)
Here you are trying to convert int to string, which is impossible to do what way.
What you are trying to do here is usual in many languages, like JavaScript. But C# has very strong rules about type conversions. And most of the time, you cannot just cast type to string and back.

Convert String To Nullable Integer List

I'm wanting to parse a string into a nullable int list in C#
I'm able to convert it to int list bit not a nullable one
string data = "1,2";
List<int> TagIds = data.Split(',').Select(int.Parse).ToList();
say when data will be empty i want to handle that part!
Thanks
You can use following extension method:
public static int? TryGetInt32(this string item)
{
int i;
bool success = int.TryParse(item, out i);
return success ? (int?)i : (int?)null;
}
Then it's simple:
List<int?> TagIds = data.Split(',')
.Select(s => s.TryGetInt32())
.ToList();
I use that extension method always in LINQ queries if the format can be invalid, it's better than using a local variable and int.TryParse (E. Lippert gave an example, follow link).
Apart from that it may be better to use data.Split(new[]{','}, StringSplitOptions.RemoveEmptyEntries) instead which omits empty strings in the first place.

Converting Text to HTML In D

I'm trying to figure the best way of encoding text (either 8-bit ubyte[] or string) to its HTML counterpart.
My proposal so far is to use a lookup-table to map the 8-bit characters
string[256] lutLatin1ToHTML;
lutLatin1ToXML[0x22] = "&quot";
lutLatin1ToXML[0x26] = "&amp";
...
in HTML that have special meaning using the function
pure string toHTML(in string src,
ref in string[256] lut) {
return src.map!(a => (lut[a] ? lut[a] : new string(a))).reduce!((a, b) => a ~ b) ;
}
I almost work except for the fact that I don't know how to create a string from a `ubyte? (the no-translation case).
I tried
writeln(new string('a'));
but it prints garbage and I don't know why.
For more details on HTML encoding see https://en.wikipedia.org/wiki/Character_entity_reference
You can make a string from a ubyte most easily by doing "" ~ b, for example:
ubyte b = 65;
string a = "" ~ b;
writeln(a); // prints A
BTW, if you want to do a lot of html stuff, my dom.d and characterencodings.d might be useful:
https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff
It has a html parser, dom manipulation functions similar to javascript (e.g. ele.querySelector(), getElementById, ele.innerHTML, ele.innerText, etc.), conversion from a few different character encodings, including latin1, and outputs ascii safe html with all special and unicode characters properly encoded.
assert(htmlEntitiesEncode("foo < bar") == "foo < bar";
stuff like that.
In this case Adam's solution works just fine, of course. (It takes advantage of the fact that ubyte is implicitly convertible to char, which is then appended to the immutable(char)[] array for which string is an alias.)
In general the safe way of converting types is to use std.conv.
import std.stdio, std.conv;
void main() {
// utf-8
char cc = 'a';
string s1 = text(cc);
string s2 = to!string(cc);
writefln("%c %s %s", cc, s1, s2);
// utf-16
wchar wc = 'a';
wstring s3 = wtext(wc);
wstring s4 = to!wstring(wc);
writefln("%c %s %s", wc, s3, s4);
// utf-32
dchar dc = 'a';
dstring s5 = dtext(dc);
dstring s6 = to!dstring(dc);
writefln("%c %s %s", dc, s5, s6);
ubyte b = 65;
string a = to!string(b);
}
NB. text() is actually intended for processing multiple arguments, but is conveniently short.

Resources