starwing / lua-protobuf

A Lua module to work with Google protobuf
MIT License
1.75k stars 387 forks source link

merge_from suport? #200

Open stillcold opened 2 years ago

stillcold commented 2 years ago

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 )
starwing commented 2 years ago

You could just concat two bytes to merge:

local a = pb.encode(...)
local b = pb.encode(...)
local result = a .. b
stillcold commented 2 years ago

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. :)

starwing commented 2 years ago

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.

stillcold commented 2 years ago

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

Thanks.