| Crates.io | lua-protobuf-rs |
| lib.rs | lua-protobuf-rs |
| version | 0.3.0 |
| created_at | 2023-10-13 17:07:15.949623+00 |
| updated_at | 2025-09-10 12:54:40.732575+00 |
| description | lua protobuf |
| homepage | https://github.com/mikai233/lua-protobuf-rs |
| repository | https://github.com/mikai233/lua-protobuf-rs |
| max_upload_size | |
| id | 1002492 |
| size | 8,913,382 |
Available languages: English | 中文
This project provides a Lua library for parsing Protobuf, built on top of Rust’s protobuf implementation.
It allows you to:
.proto files at runtimeThe bound APIs can be found here, and almost all APIs are exposed.
--- @type LuaProtoc
local luaProtoc = require("lua_protobuf_rs")
---@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.parse_proto(proto)
local player = {
id = 2347239423213,
world_id = 234872389,
nickname = "mikai233",
exp = 22000,
}
local player_bytes = protoc:encode("Player", player)
local decode_player = protoc:decode("Player", player_bytes)
print(decode_player.id)
local login_response_bytes = protoc:encode("LoginResponse", {})
local decode_login_response = protoc:decode("LoginResponse", login_response_bytes)
print(decode_login_response.player.id)
syntax = "proto3";
package com.mikai233;
message Player{
int64 id = 1;
int64 world_id = 2;
string nickname = 3;
int32 exp = 4;
}
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("lua_protobuf_rs")
local protos = luaProtoc.list_protos({ "proto" })
local protoc = luaProtoc.parse_files(protos, { "proto" })
local player = {
id = 2347239423213,
world_id = 234872389,
nickname = "mikai233",
exp = 22000,
}
local player_bytes = protoc:encode("com.mikai233.Player", player)
local decode_player = protoc:decode("com.mikai233.Player", player_bytes)
print(decode_player.id)
local login_response_bytes = protoc:encode("com.mikai233.LoginResponse", {})
local decode_login_response = protoc:decode("com.mikai233.LoginResponse", login_response_bytes)
print(decode_login_response.player.id)
For more reflection APIs, please refer to the documentation.
--- @type LuaProtoc
local luaProtoc = require("lua_protobuf_rs")
local protos = luaProtoc.list_protos({ "proto" })
local protoc = luaProtoc.parse_files(protos, { "proto" })
local player_descriptor = protoc:message_descriptor_by_name("com.mikai233.Player")
for _, field in pairs(player_descriptor:fields()) do
print("field name: " .. field:name() .. " number: " .. field:number())
end
print("====")
local login_response_descriptor = protoc:message_descriptor_by_name("com.mikai233.LoginResponse")
for _, field in pairs(login_response_descriptor:fields()) do
local rt = field:runtime_field_type()
if rt.singular then
local singular = rt.singular
print(singular.message:name())
end
end
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
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);
}
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.
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
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.