lua-protobuf-rs
Available languages: English | 中文
This project provides a Lua library for parsing Protobuf, built on top of Rust’s protobuf implementation.
It allows you to:
- Load
.proto
files at runtime - Parse Protobuf binary data into Lua tables
- Encode Lua tables into Protobuf binary data
- Use Protobuf reflection features in Lua
The bound APIs can be found here, and almost all APIs are exposed.
Usage
Parse proto directly in Lua
--- @type LuaProtoc
local luaProtoc = require
---@language "protobuf"
local proto = [[
syntax="proto3";
message Player{
int64 id = 1;
int64 world_id = 2;
string nickname = 3;
int32 exp = 4;
}
message LoginRequest{
int64 id = 1;
int64 world_id = 2;
}
message LoginResponse{
Player player = 1;
}
]]
local protoc = luaProtoc.
local player =
local player_bytes = protoc:
local decode_player = protoc:
print
local login_response_bytes = protoc:
local decode_login_response = protoc:
print
Parse proto files in Lua
- player.proto
syntax = "proto3";
package com.mikai233;
message Player{
int64 id = 1;
int64 world_id = 2;
string nickname = 3;
int32 exp = 4;
}
- login.proto
syntax = "proto3";
import "player.proto";
package com.mikai233;
message LoginRequest{
int64 id = 1;
int64 world_id = 2;
}
message LoginResponse{
Player player = 1;
}
--- @type LuaProtoc
local luaProtoc = require
local protos = luaProtoc.
local protoc = luaProtoc.
local player =
local player_bytes = protoc:
local decode_player = protoc:
print
local login_response_bytes = protoc:
local decode_login_response = protoc:
print
Reflection
For more reflection APIs, please refer to the documentation.
--- @type LuaProtoc
local luaProtoc = require
local protos = luaProtoc.
local protoc = luaProtoc.
local player_descriptor = protoc:
for _, field in pairs
print
local login_response_descriptor = protoc:
for _, field in pairs
Proto code hints
You can use gen_lua
to generate Lua proto template files for better development experience.
This project uses annotations based on the EmmyLua
plugin.
---@class LoginRequest
---@field id number
---@field world_id number
local LoginRequest
---@class LoginResponse
---@field player Player
local LoginResponse
xLua integration
Set the environment variables LUA_LIB_NAME
and LUA_LIB
to point to the xLua header directory and library name, then
recompile this project.
⚠️ Make sure the xLua version matches the Lua version used in this project.
[DllImport("lua_protobuf_rs", CallingConvention = CallingConvention.Cdecl)]
public static extern int luaopen_lua_protobuf_rs(System.IntPtr L);
[MonoPInvokeCallback(typeof(LuaDLL.lua_CSFunction))]
public static int LoadProtobufRs(System.IntPtr L)
{
return luaopen_lua_protobuf_rs(L);
}
Build
Thanks to Cargo, building is very simple. Just install Rust, then run:
cargo build --release
to get the library file for the current platform.
For different Lua versions, modify the default
field in Cargo.toml
and rebuild.
Cross-compilation
If you need to build for other platforms, you can use cross-rs , which requires Docker but is very straightforward.
-
Build for Linux:
cross build --target x86_64-unknown-linux-gnu --release
-
Build for Android:
cross build --target armv7-linux-androideabi --release
Notes
For non-oneof
fields, when parsing binary messages into a Lua table, unset fields will get default values.
For oneof
fields, if no value is set, then all fields will be absent.
That means: in a oneof
, only one field can exist at a time, or none at all.