1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use std::fs;
use std::path::Path;
fn main() {
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let out_dir = std::env::var("OUT_DIR").unwrap();
// lua/ lives at the workspace root (two levels up from crates/ff-script/)
let lua_dir = Path::new(&manifest_dir).join("../../lua");
let output_path = Path::new(&out_dir).join("flowfabric.lua");
// Ordered list of Lua source files. Helpers MUST come first since all
// registered functions depend on the library-local helpers.
let lua_files: &[&str] = &[
"helpers.lua",
"version.lua",
"lease.lua",
"execution.lua",
"scheduling.lua",
"suspension.lua",
"signal.lua",
"stream.lua",
"budget.lua",
"quota.lua",
"flow.lua",
];
let mut output = String::new();
// Preamble: library declaration (required by Valkey Functions)
output.push_str("#!lua name=flowfabric\n");
for filename in lua_files {
let path = lua_dir.join(filename);
let source = fs::read_to_string(&path).unwrap_or_else(|e| {
panic!("Failed to read {}: {}", path.display(), e);
});
output.push_str(&format!("\n-- source: lua/{}\n", filename));
output.push_str(&source);
output.push('\n');
}
fs::write(&output_path, &output).unwrap_or_else(|e| {
panic!("Failed to write {}: {}", output_path.display(), e);
});
// Single source of truth for LIBRARY_VERSION: extract the string
// literal from `lua/version.lua` and expose it to Rust via
// `cargo:rustc-env=FLOWFABRIC_LUA_VERSION=...`. `crates/ff-script/src/lib.rs`
// reads it through `env!("FLOWFABRIC_LUA_VERSION")`. Eliminates the
// two-place drift class (one bump updates both the Lua function and
// the Rust constant the loader compares against).
//
// Parse contract: `lua/version.lua` must contain exactly one
// `return 'X'` literal (the body of `ff_version`). String find+slice,
// no regex or Lua parser dependency. Break the contract → panic with
// a message that points at the file to fix.
let version_path = lua_dir.join("version.lua");
let version_source = fs::read_to_string(&version_path).unwrap_or_else(|e| {
panic!("Failed to read {}: {}", version_path.display(), e);
});
// Walk lines, skipping Lua comments ("--" at start after trimming).
// The version.lua docstring contains "return 'X'" as explanatory text;
// a naive `version_source.find("return '")` picks that up instead of
// the real function body. Line-based skip-comments parse keeps the
// extract string-based (no regex dep) while avoiding that trap.
//
// Strict "exactly one" contract: collect ALL non-comment matches, then
// panic if count != 1. Guards against a future edit that adds a second
// `register_function` returning a literal and silently takes the
// first match (or worse, the wrong match).
let matches: Vec<String> = version_source
.lines()
.filter_map(|raw| {
let line = raw.trim_start();
if line.starts_with("--") {
return None;
}
let i = line.find("return '")?;
let rest = &line[i + "return '".len()..];
rest.find('\'').map(|j| rest[..j].to_owned())
})
.collect();
let version = match matches.len() {
1 => matches.into_iter().next().unwrap(),
0 => panic!(
"Failed to extract LIBRARY_VERSION from {}: expected exactly one \
non-commented `return 'X'` literal (the body of ff_version), found \
NONE. Do NOT maintain a separate copy in crates/ff-script/src/lib.rs \
— this extract is the single source of truth.",
version_path.display()
),
n => panic!(
"Failed to extract LIBRARY_VERSION from {}: expected exactly one \
non-commented `return 'X'` literal, found {n} ({matches:?}). If \
version.lua grew a second register_function, move it elsewhere — \
the extract can't know which one is authoritative.",
version_path.display()
),
};
// Sanity bounds: non-empty, no embedded quotes/newlines that would
// imply a broken parse, short enough to be a version string.
assert!(
!version.is_empty()
&& version.len() < 64
&& !version.contains('\n')
&& !version.contains('\''),
"Invalid LIBRARY_VERSION extracted from lua/version.lua: {version:?}"
);
println!("cargo:rustc-env=FLOWFABRIC_LUA_VERSION={version}");
// Tell Cargo to re-run if any Lua file changes. `version.lua` is
// already in the list above, so changes to it trigger re-extract.
for filename in lua_files {
println!("cargo:rerun-if-changed=../../lua/{}", filename);
}
}