lua-protobuf icon indicating copy to clipboard operation
lua-protobuf copied to clipboard

merge_from suport?

Open stillcold opened this issue 3 years ago • 4 comments

Hi guys, is there any plan about supporting merge_from inteface?

The code below is a example.

As far as I can see, I have to use pb.fields to traverse all the fields and try to merge the values. But I don't think it is a good idea, any suggestions about the implements?

local pb = require "pb"
local protoc = require "protoc"

assert(protoc:load [[
    message Phone {
        optional string name        = 1;
        optional int64  phonenumber = 2;
    }
    message Person {
        optional string name     = 1;
        optional int32  age      = 2;
        optional string address  = 3;
        repeated Phone  contacts = 4;
    }
    message Chinese {
        optional string name     = 1;
        optional int32  age      = 2;
        optional string address  = 3;
        repeated Phone  contacts = 4;
        optional string wechat   = 5;
    }
]])

-- lua table data
local chinese_data = {
   name = "ilse",
   age  = 18,
   wechat = "+86-13333333333",
   contacts = {
      { name = "alice", phonenumber = 12312341234 },
      { name = "bob",   phonenumber = 45645674567 }
   }
}

local person_data = pb.merge_from("Person", chinese_data )

stillcold avatar May 27 '22 03:05 stillcold

You could just concat two bytes to merge:

local a = pb.encode(...)
local b = pb.encode(...)
local result = a .. b

starwing avatar May 27 '22 03:05 starwing

This is wondeful, but not what I mean. So I am very sorry about that I didn't give you a exact demo.

What I mean is:

local person_data = pb.merge_from("Person", chinese_data )

like a filter, a merger_from function just ignores the useless keys and keeps what we defined. In this way, it merge data for Person proto from a packet decoded from Chinese proto. The two protos may have similar keys. person_data is some thing like chinese_data, it is also a lua table, not in bytes. after do that, the content in person_data should be:

 {
   name = "ilse",
   age  = 18,
   contacts = {
      { name = "alice", phonenumber = 12312341234 },
      { name = "bob",   phonenumber = 45645674567 }
   }
}

All keys in chinese_data but not defined in Person proto are gone.

A merge operation is more like:

-- well, this is another implement, but i think it is inefficient
function pb.merge_from(pb_type, data)
       return pb.decode(pb_type, pb.encode(pb_type, data))
end

In my project, I am using a lua implement instead, but that is also inefficient. Thanks. :)

stillcold avatar May 27 '22 06:05 stillcold

In my project, I am using a lua implement instead, but that is also inefficient.

We're using this, too. And it works perfect. It's may not be fatter to add a new routine to do so.

Because merging tables means traverse all table recursive, traverse the source message information and destination message information. That is just the most cost in encode/decode. So it may helpless for the performance.

starwing avatar May 27 '22 08:05 starwing

I'll run some tests. I'll keep you posted.

Thanks.

stillcold avatar May 27 '22 08:05 stillcold