serde_luaq

[!NOTE] This library is still a work in progress, and there are no API stability guarantees.
serde_luaq is a library for deserialising (and eventually, serialising) simple, JSON-equivalent
data structures from Lua 5.4 source code, without requiring Lua itself (unlike mlua).
The goal is to be able to read state from software (mostly games) which is serialised using
Lua %q formatting (and similar techniques) without requiring arbitrary code execution.
This library consists of four parts:
-
A
LuaValueenum, which describes Lua 5.4's basic data types (nil, boolean, string, number, table). -
A
peg-based parser for parsing a&[u8](containing Lua) into aLuaValue. -
A Serde-based
Deserializeimplementation for converting aLuaValueinto your own data types. -
Optional lossy converter to and from
serde_json'sValuetype.
Goal
For example, you could have a Lua script like this:
a = 1
b =
c =
And define some a schema using Serde traits:
Then deserialise it with:
use ;
let parsed: Test = from_slice.unwrap;
assert_eq!;
Parser features
- Input formats
- Bare Lua value expression, similar to JSON (
{["hello"] = "world"}) - Lua return statement (
return {["hello"] = "world"}) - Script with identifier assignments only (
hello = "world")
- Bare Lua value expression, similar to JSON (
- Serde (partial)
- Deserialising
- Serialising
- Lossy
serde_jsoninteroperability-
LuaValue->serde_json::Value -
serde_json::Value->LuaValue
-
Lua language features
This library aims to implement a subset of Lua 5.4 that is equivalent to the subset of JavaScript that a JSON parser would implement:
-
nil - Booleans (
true,false) - Numbers
- Integers (
i64only)- Decimal integers (
123)- Coercion to float for decimal numbers
< i64::MINor> i64::MAX(Lua 5.4)
- Coercion to float for decimal numbers
- Hexadecimal integers (
0xFF)- Wrapping large hexadecimal numbers to
i64
- Wrapping large hexadecimal numbers to
- Decimal integers (
- Floats (
f64only)- Decimal floats with decimal point and optional exponent (
3.14,0.314e1) - Decimal floats with mandatory exponent (
3e14) - Hexadecimal floating points (
0x.ABCDEFp+24) (not supported on WASM before v0.2.1) - Positive and negative infinity (
1e9999,-1e9999) - NaN (
(0/0))
- Decimal floats with decimal point and optional exponent (
- Integers (
- Strings
- Strings in single quotes (
') - Strings in double quotes (
") - Strings in long brackets (
[[string]],[==[string]==]) (up to 5=deep) - Arbitrary 8-bit binary data inside strings (like
[u8]) - Escapes in quoted strings:
- C-like backslash-escapes (
abfnrtv\"') - Escaped line breaks (
\\\n,\\\r,\\\r\n,\\\n\r) -
\zwhitespace span escapes (str\z ing==string) - Decimal escape sequences (
\1,\01,\001) - Hexadecimal escape sequences (
\x01) - UTF-8 escape sequences (
\u{1F4A9})- Sequences allowed by RFC 2279 but not RFC 3629 (
\u{D800},\u{7FFFFFFF})
- Sequences allowed by RFC 2279 but not RFC 3629 (
- C-like backslash-escapes (
- Strings in single quotes (
- Tables
- Key-values / expression keys (
{["foo"] = "bar"},{[1234]="bar"}) - Name-values / identifier keys (
{foo = "bar"})- Identifier validation (Lua 5.4-style)
- Values / implicit keys (
{"bar"}) - Mixed key types
- Recursion depth limits
- Key-values / expression keys (
This library is not designed to replace Lua, nor execute arbitrary Lua code, so these Lua features are intentionally unsupported:
- Arithmetic operators (
+,-,*,/...) - Bitwise operators (
<<,>>,&,|,~...) - Blocks and control structures (
if,break,do,end,for,goto,repeat,until,while...) - Comments
- Function calls
- Function definitions
- Length operator (
#) - Locale-specific behaviour (
3,14159) - Logical operators (
and,or,not) - Newline character normalisation in strings (
\r\n=>\non UNIX,\n=>\r\non Windows) - Parentheses, except for
(0/0)(NaN) - Pointers (light userdata)
- Referencing other variables (
a = 10; b = a) - Relational operators (
==,~=,<,>...) - String concatenation (
"hello" .. " world") - Threads and coroutines
- Updating other variables (
a = {}; a.b = 'foo') - Userdata
- Vararg assignments and destructuring (
a, b = 1, 2) - Variable attributes and visibility modifiers (
local <const> a = 10)
If you want to use these language features or otherwise need to run arbitrary Lua code, look at
something like mlua, which links to liblua, and also provides serde bindings.
Known users of Lua serialisation
-
Programming in Lua has a function that dumps a Lua table into a file as a script.
-
SaveData: Love2D library, emits a
returnstatement which is loaded by evaluating the string. -
Balatro (
engine/string_packer.lua) is a modified version ofSaveDatathat also compresses withdeflatefor save games and settings (.jkrfiles). -
World of Warcraft: addon state, written to
WTF/{Account,SavedVariables}/**/*.luaas scripts that set variables.
License
This project is dual-licensed under the terms of the Apache-2.0 and MIT licenses.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed under the terms of the Apache-2.0 and MIT licenses, without any additional terms or conditions.
serde_luaq does not include any copy of Lua itself. To ensure maximal compatibility with Lua's
syntax, some of its test cases are derived from Lua's test suite.