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

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.

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.

Response architecture

I have the following question.
I have an endpoint which returns some data with the following format.
[
{
avr_video_likes = 15;
avr_video_likes_ratio = 3;
avr_video_views = 1500;
avr_views_ratio = 7.2;
avr_video_comments = 4;
avr_video_comments_ratio = 75;
}
.....
]
the possible values are 0 or positive ones.
So I was wondering, if a value doesnt exist at all in my database which is the the best response to send.
Return -1 in order to show that the value doesnt exist. Because values are type of number
Return "-"
Dont return the value at all.
Which one is the best option and why?
Thank you for your time

convert protobuf to other protobuf

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);

ArgumentException while reading using readblock streamreader

I am trying to calculate row count from a large file based on presence of a certain character and would like to use StreamReader and ReadBlock - below is my code.
protected virtual long CalculateRowCount(FileStream inStream, int bufferSize)
{
long rowCount=0;
String line;
inStream.Position = 0;
TextReader reader = new StreamReader(inStream);
char[] block = new char[4096];
const int blockSize = 4096;
int indexer = 0;
int charsRead = 0;
long numberOfLines = 0;
int count = 1;
do
{
charsRead = reader.ReadBlock(block, indexer, block.Length * count);
indexer += blockSize ;
numberOfLines = numberOfLines + string.Join("", block).Split(new string[] { "&ENDE" }, StringSplitOptions.None).Length;
count ++;
} while (charsRead == block.Length);//charsRead !=0
reader.Close();
fileRowCount = rowCount;
return rowCount;
}
But I get error
Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
I am not sure what is wrong... Can you help. Thanks ahead!
For one, read the StreamReader.ReadBlock() documentation carefully http://msdn.microsoft.com/en-us/library/system.io.streamreader.readblock.aspx and compare with what you're doing:
The 2nd argument (indexer) should be within the range of the block you're passing in, but you're passing something that will probably exceed it after one iteration. Since it looks like you want to reuse the memory block, pass 0 here.
The 3rd argument (count) indicates how many bytes to read into your memory block; passing something larger than the block size might not work (depends on implementation)
ReadBlock() returns the number of bytes actually read, but you increment indexer as if it will always return the size of the block exactly (most of the time, it won't)

clistbox gettext error

I am trying to add items from alistbox to cstringarray. But text is null always. plz suggest the changes
int count = m_OutList.GetCount();
for ( i = 0; i <m_OutList.GetCount(); i++)
{
m_OutList.GetText( buf[i], text );
m_selcomponents->Add(text);
// getb //Add();
}
If text is a CString in your example, you need to write m_OutList.GetText(i,text) - you don't need a buffer variable if you pass a CString&. buf[i] is a part of your buffer and has a random value.

Resources