Skip to content

Commit ccb0607

Browse files
committed
add more test
1 parent db3d4a1 commit ccb0607

File tree

13 files changed

+939
-123
lines changed

13 files changed

+939
-123
lines changed

Cargo.lock

Lines changed: 95 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/luars/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ libloading = { workspace = true, optional = true }
1515
tokio = { workspace = true, optional = true }
1616
itoa = "1.0" # Fast integer formatting (10x faster than format!)
1717
ryu = "1.0" # Fast float formatting
18+
tempfile = "3.10" # For io.tmpfile()

crates/luars/src/lua_vm/execute/table_instructions.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,9 +540,12 @@ pub fn exec_self(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> Lu
540540
vm.register_stack[base_ptr + a + 1] = table;
541541

542542
// R[A] := R[B][K[C]] (method)
543-
let method = vm
544-
.table_get_with_meta(&table, &key)
545-
.unwrap_or(crate::LuaValue::nil());
543+
// Support both tables and userdata
544+
let method = if table.is_userdata() {
545+
vm.userdata_get(&table, &key).unwrap_or(crate::LuaValue::nil())
546+
} else {
547+
vm.table_get_with_meta(&table, &key).unwrap_or(crate::LuaValue::nil())
548+
};
546549
vm.register_stack[base_ptr + a] = method;
547550

548551
Ok(())

crates/luars/src/stdlib/basic.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,30 @@ fn lua_getmetatable(vm: &mut LuaVM) -> LuaResult<MultiValue> {
425425
Ok(MultiValue::single(LuaValue::nil()))
426426
}
427427
}
428-
// TODO: Support metatables for other types (userdata, numbers, etc.)
428+
LuaValueKind::Userdata => {
429+
// Return userdata metatable
430+
if let Some(ud_id) = value.as_userdata_id() {
431+
if let Some(ud) = vm.object_pool.get_userdata(ud_id) {
432+
let mt = ud.get_metatable();
433+
if !mt.is_nil() {
434+
// Check for __metatable field
435+
let metatable_key = vm.create_string("__metatable");
436+
if let Some(mt_id) = mt.as_table_id() {
437+
if let Some(mt_table) = vm.object_pool.get_table(mt_id) {
438+
if let Some(protected) = mt_table.raw_get(&metatable_key) {
439+
if !protected.is_nil() {
440+
return Ok(MultiValue::single(protected));
441+
}
442+
}
443+
}
444+
}
445+
return Ok(MultiValue::single(mt));
446+
}
447+
}
448+
}
449+
Ok(MultiValue::single(LuaValue::nil()))
450+
}
451+
// TODO: Support metatables for other types (numbers, etc.)
429452
_ => Ok(MultiValue::single(LuaValue::nil())),
430453
}
431454
}

crates/luars/src/stdlib/io/file.rs

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ impl LuaFile {
4040
let file = std::fs::OpenOptions::new()
4141
.write(true)
4242
.append(true)
43+
.create(true)
4344
.open(path)?;
4445
Ok(LuaFile {
4546
inner: FileInner::Write(BufWriter::new(file)),
@@ -50,11 +51,24 @@ impl LuaFile {
5051
let file = std::fs::OpenOptions::new()
5152
.read(true)
5253
.write(true)
54+
.create(true)
5355
.open(path)?;
5456
Ok(LuaFile {
5557
inner: FileInner::ReadWrite(file),
5658
})
5759
}
60+
61+
/// Create from existing File (for tmpfile)
62+
pub fn from_file(file: File) -> Self {
63+
LuaFile {
64+
inner: FileInner::ReadWrite(file),
65+
}
66+
}
67+
68+
/// Check if file is closed
69+
pub fn is_closed(&self) -> bool {
70+
matches!(self.inner, FileInner::Closed)
71+
}
5872

5973
/// Read operations
6074
pub fn read_line(&mut self) -> io::Result<Option<String>> {
@@ -220,15 +234,31 @@ fn file_read(vm: &mut LuaVM) -> LuaResult<MultiValue> {
220234
let mut data_ref = data.borrow_mut();
221235
if let Some(lua_file) = data_ref.downcast_mut::<LuaFile>() {
222236
// Get format (default "*l") - register 2 is first argument after self
223-
let format_str = if let Some(fmt) = get_arg(vm, 2) {
224-
if let Some(s) = vm.get_string(&fmt) {
225-
s.as_str().to_string()
226-
} else {
227-
"*l".to_string()
237+
let format_arg = get_arg(vm, 2);
238+
239+
// Check if format is a number (byte count)
240+
if let Some(ref fmt) = format_arg {
241+
if let Some(n) = fmt.as_integer() {
242+
// Read n bytes
243+
match lua_file.read_bytes(n as usize) {
244+
Ok(bytes) => {
245+
if bytes.is_empty() {
246+
return Ok(MultiValue::single(LuaValue::nil()));
247+
}
248+
let s = String::from_utf8_lossy(&bytes);
249+
return Ok(MultiValue::single(vm.create_string(&s)));
250+
}
251+
Err(e) => {
252+
return Err(vm.error(format!("read error: {}", e)));
253+
}
254+
}
228255
}
229-
} else {
230-
"*l".to_string()
231-
};
256+
}
257+
258+
// Otherwise treat as format string
259+
let format_str = format_arg
260+
.and_then(|v| vm.get_string(&v).map(|s| s.as_str().to_string()))
261+
.unwrap_or_else(|| "*l".to_string());
232262
let format = format_str.as_str();
233263

234264
let result = match format {
@@ -241,13 +271,34 @@ fn file_read(vm: &mut LuaVM) -> LuaResult<MultiValue> {
241271
Ok(content) => vm.create_string(&content),
242272
Err(e) => return Err(vm.error(format!("read error: {}", e))),
243273
},
274+
"*n" => {
275+
// Read a number
276+
match lua_file.read_line() {
277+
Ok(Some(line)) => {
278+
let trimmed = line.trim();
279+
if let Ok(n) = trimmed.parse::<i64>() {
280+
LuaValue::integer(n)
281+
} else if let Ok(n) = trimmed.parse::<f64>() {
282+
LuaValue::float(n)
283+
} else {
284+
LuaValue::nil()
285+
}
286+
}
287+
Ok(None) => LuaValue::nil(),
288+
Err(e) => return Err(vm.error(format!("read error: {}", e))),
289+
}
290+
}
244291
_ => {
245-
// Try to parse as number (byte count)
292+
// Try to parse as number (byte count) from string like "10"
246293
if let Ok(n) = format.parse::<usize>() {
247294
match lua_file.read_bytes(n) {
248295
Ok(bytes) => {
249-
let s = String::from_utf8_lossy(&bytes);
250-
vm.create_string(&s)
296+
if bytes.is_empty() {
297+
LuaValue::nil()
298+
} else {
299+
let s = String::from_utf8_lossy(&bytes);
300+
vm.create_string(&s)
301+
}
251302
}
252303
Err(e) => {
253304
return Err(vm.error(format!("read error: {}", e)));

0 commit comments

Comments
 (0)