lua_types/filehandle.rs
1//! Minimal file-handle abstraction shared between `lua-vm` (hook type) and
2//! `lua-stdlib` (io library).
3//!
4//! `std::fs` and `std::io` are banned in `lua-stdlib` by PORTING.md §1. The
5//! concrete implementation (backed by `std::fs::File`) lives in `lua-cli` and
6//! is installed via [`crate::error::LuaError`]-returning function pointers on
7//! [`lua_vm::state::GlobalState`]. This trait is the shared seam that allows
8//! `lua-stdlib` to program against file handles without importing `std::fs`.
9//!
10//! ## Trait design
11//! The trait mirrors the subset of `LuaFileOps` (defined in `lua-stdlib`) that
12//! is required to run the built-in io library at the level needed for
13//! `attrib.lua`-class tests: sequential write, byte-by-byte read, flush, and
14//! seek. `LuaFileOps` in `lua-stdlib` extends this trait so that a single
15//! concrete type (the `FsFile` in `lua-cli`) satisfies both.
16
17use std::io::{self, SeekFrom};
18
19/// Capabilities required by the io library from an OS file handle.
20///
21/// Designed to be object-safe (`Box<dyn LuaFileHandle>`). Implementations
22/// backed by `std::fs::File` live in `lua-cli`; implementations for the
23/// standard streams live in `lua-stdlib/src/io_lib.rs`.
24pub trait LuaFileHandle: Send {
25 /// Read one byte from the handle; return it as `i32`, or `-1` on EOF/error.
26 fn read_byte(&mut self) -> i32;
27
28 /// Push back a previously-read byte so the next `read_byte` returns it.
29 fn unread_byte(&mut self, byte: i32);
30
31 /// Write a byte slice; return the number of bytes actually written.
32 fn write_bytes(&mut self, data: &[u8]) -> io::Result<usize>;
33
34 /// Flush any write buffers to the underlying OS handle.
35 fn flush(&mut self) -> io::Result<()>;
36
37 /// Seek within the file.
38 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64>;
39
40 /// Return the current file position without moving it.
41 fn tell(&mut self) -> io::Result<u64>;
42
43 /// Clear the error/EOF flag on the handle.
44 fn clear_error(&mut self);
45
46 /// Return `true` if the handle has a pending error.
47 fn has_error(&self) -> bool;
48
49 /// Control write buffering. Mode values mirror `file:setvbuf` option order:
50 /// 0 = no buffering, 1 = full buffering, 2 = line buffering.
51 fn set_buf_mode(&mut self, _mode: i32, _size: usize) -> io::Result<()> {
52 Ok(())
53 }
54}
55
56// ──────────────────────────────────────────────────────────────────────────
57// PORT STATUS
58// source: (new abstraction — not a direct port of a C file)
59// target_crate: lua-types
60// confidence: high
61// todos: 0
62// port_notes: 0
63// unsafe_blocks: 0
64// notes: Introduced in Phase B to break the dependency cycle that
65// would arise if `lua-vm` tried to use `LuaFileOps` from
66// `lua-stdlib`. The concrete `FsFile` implementation in
67// `lua-cli` implements this trait; `LuaFileOps` in
68// `lua-stdlib` is a type alias for this same trait.
69// ──────────────────────────────────────────────────────────────────────────