@@ -382,8 +382,9 @@ pub const Lua = struct {
382
382
}
383
383
384
384
/// Dumps a function as a binary chunk
385
- pub fn dump (lua : * Lua , writer : CWriterFn , data : * anyopaque , strip : bool ) i32 {
386
- return c .lua_dump (lua .state , writer , data , @boolToInt (strip ));
385
+ /// Returns an error if writing was unsuccessful
386
+ pub fn dump (lua : * Lua , writer : CWriterFn , data : * anyopaque , strip : bool ) ! void {
387
+ if (c .lua_dump (lua .state , writer , data , @boolToInt (strip )) != 0 ) return Error .Fail ;
387
388
}
388
389
389
390
/// Raises a Lua error using the value at the top of the stack as the error object
@@ -446,6 +447,7 @@ pub const Lua = struct {
446
447
}
447
448
448
449
/// Pushes onto the stack the value of the global `name`. Returns the type of that value
450
+ /// NOTE: could return an error if it was successful (not nil)
449
451
pub fn getGlobal (lua : * Lua , name : [:0 ]const u8 ) LuaType {
450
452
return @intToEnum (LuaType , c .lua_getglobal (lua .state , name ));
451
453
}
@@ -564,23 +566,21 @@ pub const Lua = struct {
564
566
}
565
567
566
568
/// Loads a Lua chunk without running it
567
- pub fn load (lua : * Lua , reader : CReaderFn , data : * anyopaque , chunk_name : [:0 ]const u8 , mode : ? Mode ) ! void {
568
- const mode_str = blk : {
569
- if (mode == null ) break :blk "bt" ;
570
-
571
- break :blk switch (mode .? ) {
572
- .binary = > "b" ,
573
- .text = > "t" ,
574
- .binary_text = > "bt" ,
575
- };
569
+ pub fn load (lua : * Lua , reader : CReaderFn , data : * anyopaque , chunk_name : [:0 ]const u8 , mode : Mode ) ! void {
570
+ const mode_str = switch (mode ) {
571
+ .binary = > "b" ,
572
+ .text = > "t" ,
573
+ .binary_text = > "bt" ,
576
574
};
577
575
const ret = c .lua_load (lua .state , reader , data , chunk_name , mode_str );
578
576
switch (ret ) {
579
577
Status .ok = > return ,
580
578
Status .err_syntax = > return Error .Syntax ,
581
579
Status .err_memory = > return Error .Memory ,
582
- // NOTE: the docs mention possible other return types, but I couldn't figure them out
583
- else = > panic ("load returned an unexpected status: `{d}`" , .{ret }),
580
+ // can also return any result of a pcall error
581
+ Status .err_runtime = > return Error .Runtime ,
582
+ Status .err_error = > return Error .MsgHandler ,
583
+ else = > unreachable ,
584
584
}
585
585
}
586
586
@@ -810,9 +810,9 @@ pub const Lua = struct {
810
810
}
811
811
812
812
/// Resets a thread, cleaning its call stack and closing all pending to-be-closed variables
813
- /// TODO: look into possible errors
814
- pub fn resetThread (lua : * Lua ) i32 {
815
- return c .lua_resetthread (lua .state );
813
+ /// Returns an error if an error occured and leaves an error object on top of the stack
814
+ pub fn resetThread (lua : * Lua ) ! void {
815
+ if ( c .lua_resetthread (lua .state ) != Status . ok ) return Error . Fail ;
816
816
}
817
817
818
818
/// Starts and resumes a coroutine in the given thread
@@ -1728,7 +1728,7 @@ fn wrapZigReaderFn(comptime f: ZigReaderFn) CReaderFn {
1728
1728
var lua : Lua = .{ .state = state .? };
1729
1729
if (@call (.{ .modifier = .always_inline }, f , .{ & lua , data .? })) | buffer | {
1730
1730
size .* = buffer .len ;
1731
- return buffer ;
1731
+ return buffer . ptr ;
1732
1732
} else {
1733
1733
size .* = 0 ;
1734
1734
return null ;
@@ -1751,15 +1751,14 @@ fn wrapZigWarnFn(comptime f: ZigWarnFn) CWarnFn {
1751
1751
/// Wrap a ZigWriterFn in a CWriterFn for passing to the API
1752
1752
fn wrapZigWriterFn (comptime f : ZigWriterFn ) CWriterFn {
1753
1753
return struct {
1754
- fn inner (state : ? * LuaState , buf : ? * anyopaque , size : usize , data : ? * anyopaque ) callconv (.C ) c_int {
1754
+ fn inner (state : ? * LuaState , buf : ? * const anyopaque , size : usize , data : ? * anyopaque ) callconv (.C ) c_int {
1755
1755
// this is called by Lua, state should never be null
1756
1756
var lua : Lua = .{ .state = state .? };
1757
1757
const buffer = @ptrCast ([* ]const u8 , buf )[0.. size ];
1758
- return @boolToInt (@call (
1759
- .{ .modifier = .always_inline },
1760
- f ,
1761
- .{ & lua , buffer , data .? },
1762
- ));
1758
+ const result = @call (.{ .modifier = .always_inline }, f , .{ & lua , buffer , data .? });
1759
+ // it makes more sense for the inner writer function to return false for failure,
1760
+ // so negate the result here
1761
+ return @boolToInt (! result );
1763
1762
}
1764
1763
}.inner ;
1765
1764
}
@@ -2414,24 +2413,70 @@ test "conversions" {
2414
2413
try expectEqual (@as (i32 , 1 ), lua .absIndex (-2 ));
2415
2414
}
2416
2415
2416
+ test "dump and load" {
2417
+ var lua = try Lua .init (testing .allocator );
2418
+ defer lua .deinit ();
2419
+
2420
+ // store a function in a global
2421
+ try lua .doString ("f = function(x) return function(n) return n + x end end" );
2422
+ // put the function on the stack
2423
+ _ = lua .getGlobal ("f" );
2424
+
2425
+ const writer = struct {
2426
+ fn inner (l : * Lua , buf : []const u8 , data : * anyopaque ) bool {
2427
+ _ = l ;
2428
+ var arr = @ptrCast (* std .ArrayList (u8 ), @alignCast (@alignOf (std .ArrayList (u8 )), data ));
2429
+ arr .appendSlice (buf ) catch return false ;
2430
+ return true ;
2431
+ }
2432
+ }.inner ;
2433
+
2434
+ var buffer = std .ArrayList (u8 ).init (testing .allocator );
2435
+ defer buffer .deinit ();
2436
+
2437
+ // save the function as a binary chunk in the buffer
2438
+ try lua .dump (wrap (writer ), & buffer , false );
2439
+
2440
+ // clear the stack
2441
+ try lua .resetThread ();
2442
+
2443
+ const reader = struct {
2444
+ fn inner (l : * Lua , data : * anyopaque ) ? []const u8 {
2445
+ _ = l ;
2446
+ var arr = @ptrCast (* std .ArrayList (u8 ), @alignCast (@alignOf (std .ArrayList (u8 )), data ));
2447
+ return arr .items ;
2448
+ }
2449
+ }.inner ;
2450
+
2451
+ // now load the function back onto the stack
2452
+ try lua .load (wrap (reader ), & buffer , "function" , .binary );
2453
+ try expectEqual (LuaType .function , lua .typeOf (-1 ));
2454
+
2455
+ // run the function (creating a new function)
2456
+ lua .pushInteger (5 );
2457
+ try lua .protectedCall (1 , 1 , 0 );
2458
+
2459
+ // now call the new function (which should return the value + 5)
2460
+ lua .pushInteger (6 );
2461
+ try lua .protectedCall (1 , 1 , 0 );
2462
+ try expectEqual (@as (Integer , 11 ), lua .toInteger (-1 ));
2463
+ }
2464
+
2417
2465
test "refs" {
2418
2466
// temporary test that includes a reference to all functions so
2419
2467
// they will be type-checked
2420
2468
2421
2469
// stdlib
2422
2470
_ = Lua .closeSlot ;
2423
- _ = Lua .dump ;
2424
2471
_ = Lua .raiseError ;
2425
2472
_ = Lua .getIUserValue ;
2426
2473
_ = Lua .isYieldable ;
2427
- _ = Lua .load ;
2428
2474
_ = Lua .newThread ;
2429
2475
_ = Lua .newUserdataUV ;
2430
2476
_ = Lua .next ;
2431
2477
_ = Lua .rawGetP ;
2432
2478
_ = Lua .rawSet ;
2433
2479
_ = Lua .rawSetP ;
2434
- _ = Lua .resetThread ;
2435
2480
_ = Lua .setIUserValue ;
2436
2481
_ = Lua .setMetatable ;
2437
2482
_ = Lua .setTable ;
0 commit comments