luna_core/lib.rs
1#![deny(missing_docs)]
2//! luna-core — pure-Rust Lua runtime (interpreter only).
3//!
4//! Zero third-party dependencies. The JIT-equipped variant lives in
5//! the [`luna`](https://docs.rs/luna) crate, which re-exports
6//! everything here and additionally installs the Cranelift backend.
7//!
8//! Primary dialect: Lua 5.5 (tracks official upstream).
9//! Compat modes: Lua 5.1 / 5.2 / 5.3 / 5.4.
10//!
11//! # Threading model
12//!
13//! [`vm::Vm`] is **`!Send + !Sync`** — one Vm per OS thread. The GC uses
14//! raw `NonNull<T>` over an intrusive mark-sweep heap (not
15//! reference-counted handles). Embedders wanting concurrency spawn
16//! one Vm per worker thread and exchange data via channels; async
17//! embedders use `tokio::main(flavor = "current_thread")` or a
18//! `LocalSet`. See [`docs/threading.md`](../../docs/threading.md) for
19//! canonical patterns and the post-v1.1 `feature = "send"` roadmap.
20//!
21//! # Embedding contract (script-host sandbox)
22//!
23//! The minimal embedding flow:
24//!
25//! 1. `Vm::new_minimal(version)` — empty VM, no libraries loaded, no
26//! JIT installed (the trait slots default to a no-op backend in
27//! luna-core).
28//! 2. `vm.open_base()` / `open_math()` / `open_string()` /
29//! `open_table()` / `open_coroutine()` — whitelist only the safe
30//! subset; skip `os` / `io` / `debug` / `package`.
31//! 3. `vm.set_bytecode_loading(false)` when running untrusted scripts
32//! (see caveats below).
33//! 4. `vm.set_instr_budget(Some(N))` + `vm.set_memory_cap(Some(M))`
34//! per request.
35//! 5. `vm.load(src, name)` → `vm.call_value(closure, args)`.
36//! 6. On error: `vm.error_text(&e)` + `vm.take_error_traceback()`.
37//!
38//! See `examples/embed_min.rs` for a runnable zero-dep walkthrough.
39//!
40//! ## Sandbox caveats
41//!
42//! - **JIT bypass of `instr_budget`** — the (optional) cranelift JIT
43//! compiles counted-for loops to native code that does not tick the
44//! budget. Sandbox embedders that link against `luna` (not
45//! `luna-core`) must call `vm.set_jit_enabled(false)` before
46//! running untrusted scripts.
47//! - **Bytecode load surface** — `load()` defaults to mode `"bt"`
48//! which accepts precompiled chunks, bypassing the parser's
49//! depth/opcode limits. Sandbox embedders should call
50//! `vm.set_bytecode_loading(false)`.
51//! - **`instr_budget` / `mem_cap` are fire-once** — both clear to
52//! `None` on first trip. Re-arm before each `call_value` if reusing
53//! the Vm across requests, or (recommended) create a fresh Vm per
54//! request for isolation.
55//! - **`heap.bytes()` is approximate** — internal `Vec`/`Box`
56//! capacity overhead is not auto-tracked, so the cap is a lower
57//! bound. Size it with ~2× margin over the desired hard limit;
58//! bound the Vm's lifetime as a second line of defense.
59//! - **`error()` may carry any Value** — Lua scripts can call
60//! `error({code=…, msg=…})` with a non-string payload. Use
61//! `vm.error_text(&e)` to normalize to a string, or inspect `e.0`
62//! directly when the host protocol expects structured errors.
63//! - **Native panic = Vm-fatal** — Rust panics in `NativeFn`
64//! callbacks are caught and surfaced as `LuaError("native panic:
65//! …")`, but the Vm state may be inconsistent afterwards. Drop the
66//! Vm on any error whose text starts with `"native panic:"`.
67//! - **5.1 / 5.2 lack `string.pack`/`unpack`/`packsize`** — these are
68//! 5.3+ additions, gated by version. 5.1 hosts (script host) see
69//! them as `nil` on the `string` table.
70//! - **5.1 numeric semantics** — Lua 5.1 has no integer subtype.
71//! Arithmetic and the `for` loop always produce `Value::Float`;
72//! hosts that route results back through Rust must accept either
73//! `Int` (5.3+) or `Float` (all versions).
74//! - **`collectgarbage("count")` is a timing channel** — scripts can
75//! observe rough heap pressure changes. Acceptable for typical
76//! embedding; flag if the threat model includes side-channel
77//! probing.
78
79// v1.3 Phase SS-B — `send` feature gate lit. Embedders opt in via
80// `cargo add luna-core --features send`; this surfaces the
81// `vm::SendVm` newtype (`Arc<UnsafeCell<Vm>>` + `Arc<RwLock<()>>`
82// behind the scenes) for cross-thread embedding. v1.3 ships
83// `SendVm` interp-only (`NullJitBackend`); JIT-aware `SendVm` is a
84// post-v1.3 polish item. Default-feature builds are unchanged —
85// `Vm` stays `!Send + !Sync` and bit-identical with v1.2. See
86// `.dev/rfcs/v1.3-rfc-send-arc.md` for the design, and
87// `docs/threading.md` for the embedder-facing usage patterns.
88
89pub mod compiler;
90pub mod frontend;
91pub mod jit;
92pub mod numeric;
93pub mod pattern;
94pub mod runtime;
95pub mod version;
96pub mod vm;