diff --git a/src/Lua/IO/ConsoleStandardIO.cs b/src/Lua/IO/ConsoleStandardIO.cs new file mode 100644 index 00000000..a2a35a42 --- /dev/null +++ b/src/Lua/IO/ConsoleStandardIO.cs @@ -0,0 +1,33 @@ +using Lua.Standard.Internal; + +namespace Lua.IO; + +/// +/// Default implementation of ILuaStandardIO using Console +/// +public sealed class ConsoleStandardIO : ILuaStandardIO +{ + ILuaIOStream? standardInput; + + public ILuaIOStream Input => standardInput ??= + new StandardIOStream(ILuaIOStream.CreateStreamWrapper( + ConsoleHelper.OpenStandardInput(), + LuaFileOpenMode.Read)); + + ILuaIOStream? standardOutput; + + public ILuaIOStream Output + + => standardOutput ??= + new StandardIOStream(ILuaIOStream.CreateStreamWrapper( + ConsoleHelper.OpenStandardOutput(), + LuaFileOpenMode.Write)); + + + ILuaIOStream? standardError; + + public ILuaIOStream Error => standardError ??= + new StandardIOStream(ILuaIOStream.CreateStreamWrapper( + ConsoleHelper.OpenStandardError(), + LuaFileOpenMode.Write)); +} \ No newline at end of file diff --git a/src/Lua/IO/FileSystem.cs b/src/Lua/IO/FileSystem.cs new file mode 100644 index 00000000..9e3d0f89 --- /dev/null +++ b/src/Lua/IO/FileSystem.cs @@ -0,0 +1,103 @@ +namespace Lua.IO +{ + public sealed class FileSystem : ILuaFileSystem + { + public static (FileMode, FileAccess access) GetFileMode(LuaFileOpenMode luaFileOpenMode) + { + return luaFileOpenMode switch + { + LuaFileOpenMode.Read => (FileMode.Open, FileAccess.Read), + LuaFileOpenMode.Write => (FileMode.Create, FileAccess.Write), + LuaFileOpenMode.Append => (FileMode.Append, FileAccess.Write), + LuaFileOpenMode.ReadWriteOpen => (FileMode.Open, FileAccess.ReadWrite), + LuaFileOpenMode.ReadWriteCreate => (FileMode.Truncate, FileAccess.ReadWrite), + LuaFileOpenMode.ReadAppend => (FileMode.Append, FileAccess.ReadWrite), + _ => throw new ArgumentOutOfRangeException(nameof(luaFileOpenMode), luaFileOpenMode, null) + }; + } + + public bool IsReadable(string path) + { + if (!File.Exists(path)) return false; + try + { + File.Open(path, FileMode.Open, FileAccess.Read).Dispose(); + return true; + } + catch (Exception) + { + return false; + } + } + + + ILuaIOStream Open(string path, LuaFileOpenMode luaMode, LuaFileContentType contentType) + { + var (mode, access) = GetFileMode(luaMode); + Stream stream; + + if (luaMode == LuaFileOpenMode.ReadAppend) + { + stream = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete); + } + else + { + stream = File.Open(path, mode, access, FileShare.ReadWrite | FileShare.Delete); + } + + ILuaIOStream wrapper = contentType == LuaFileContentType.Binary + ? new BinaryLuaIOStream(luaMode, stream) + : new TextLuaIOStream(luaMode, stream); + + if (luaMode == LuaFileOpenMode.ReadAppend) + { + wrapper.Seek(0, SeekOrigin.End); + } + + return wrapper; + } + + public ILuaIOStream Open(string path, LuaFileMode mode) + { + if (mode is LuaFileMode.ReadBinaryOrText) + { + return new LuaChunkStream(File.OpenRead(path)); + } + + var openMode = mode.GetOpenMode(); + var contentType = mode.GetContentType(); + return Open(path, openMode, contentType); + } + + public ILuaIOStream Open(string path, string mode) + { + var flags = LuaFileModeExtensions.ParseModeString(mode); + return Open(path, flags); + } + + public void Rename(string oldName, string newName) + { + if (oldName == newName) return; + File.Move(oldName, newName); + File.Delete(oldName); + } + + public void Remove(string path) + { + File.Delete(path); + } + + static readonly string directorySeparator = Path.DirectorySeparatorChar.ToString(); + public string DirectorySeparator => directorySeparator; + + public string GetTempFileName() + { + return Path.GetTempFileName(); + } + + public ILuaIOStream OpenTempFileStream() + { + return new TextLuaIOStream(LuaFileOpenMode.ReadAppend, File.Open(Path.GetTempFileName(), FileMode.Open, FileAccess.ReadWrite)); + } + } +} \ No newline at end of file diff --git a/src/Lua/IO/ILuaFileSystem.cs b/src/Lua/IO/ILuaFileSystem.cs index bbd2c33e..03935b7a 100644 --- a/src/Lua/IO/ILuaFileSystem.cs +++ b/src/Lua/IO/ILuaFileSystem.cs @@ -1,7 +1,4 @@ -using Lua.Internal; -using System.Text; - -namespace Lua.IO; +namespace Lua.IO; public interface ILuaFileSystem { @@ -12,133 +9,4 @@ public interface ILuaFileSystem public string DirectorySeparator { get; } public string GetTempFileName(); public ILuaIOStream OpenTempFileStream(); -} - -public interface ILuaIOStream : IDisposable -{ - public LuaFileOpenMode Mode { get; } - - public LuaFileContentType ContentType { get; } - public ValueTask ReadAllAsync(CancellationToken cancellationToken); - public ValueTask ReadLineAsync(CancellationToken cancellationToken); - public ValueTask ReadStringAsync(int count, CancellationToken cancellationToken); - public ValueTask WriteAsync(LuaFileContent content, CancellationToken cancellationToken); - public ValueTask FlushAsync(CancellationToken cancellationToken); - public void SetVBuf(LuaFileBufferingMode mode, int size); - public long Seek(long offset, SeekOrigin origin); - - public static ILuaIOStream CreateStreamWrapper(Stream stream, LuaFileOpenMode mode, LuaFileContentType contentType = LuaFileContentType.Text) - { - return contentType == LuaFileContentType.Binary - ? new BinaryLuaIOStream(mode, stream) - : new TextLuaIOStream(mode, stream); - } - - public void Close() - { - Dispose(); - } -} - -public sealed class FileSystem : ILuaFileSystem -{ - public static readonly FileSystem Instance = new(); - - public static (FileMode, FileAccess access) GetFileMode(LuaFileOpenMode luaFileOpenMode) - { - return luaFileOpenMode switch - { - LuaFileOpenMode.Read => (FileMode.Open, FileAccess.Read), - LuaFileOpenMode.Write => (FileMode.Create, FileAccess.Write), - LuaFileOpenMode.Append => (FileMode.Append, FileAccess.Write), - LuaFileOpenMode.ReadWriteOpen => (FileMode.Open, FileAccess.ReadWrite), - LuaFileOpenMode.ReadWriteCreate => (FileMode.Truncate, FileAccess.ReadWrite), - LuaFileOpenMode.ReadAppend => (FileMode.Append, FileAccess.ReadWrite), - _ => throw new ArgumentOutOfRangeException(nameof(luaFileOpenMode), luaFileOpenMode, null) - }; - } - - public bool IsReadable(string path) - { - if (!File.Exists(path)) return false; - try - { - File.Open(path, FileMode.Open, FileAccess.Read).Dispose(); - return true; - } - catch (Exception) - { - return false; - } - } - - - ILuaIOStream Open(string path, LuaFileOpenMode luaMode, LuaFileContentType contentType) - { - var (mode, access) = GetFileMode(luaMode); - Stream stream; - - if (luaMode == LuaFileOpenMode.ReadAppend) - { - stream = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete); - } - else - { - stream = File.Open(path, mode, access, FileShare.ReadWrite | FileShare.Delete); - } - - ILuaIOStream wrapper = contentType == LuaFileContentType.Binary - ? new BinaryLuaIOStream(luaMode, stream) - : new TextLuaIOStream(luaMode, stream); - - if (luaMode == LuaFileOpenMode.ReadAppend) - { - wrapper.Seek(0, SeekOrigin.End); - } - - return wrapper; - } - - public ILuaIOStream Open(string path, LuaFileMode mode) - { - if (mode is LuaFileMode.ReadBinaryOrText) - { - return new LuaChunkStream(File.OpenRead(path)); - } - - var openMode = mode.GetOpenMode(); - var contentType = mode.GetContentType(); - return Open(path, openMode, contentType); - } - - public ILuaIOStream Open(string path, string mode) - { - var flags = LuaFileModeExtensions.ParseModeString(mode); - return Open(path, flags); - } - - public void Rename(string oldName, string newName) - { - if (oldName == newName) return; - File.Move(oldName, newName); - File.Delete(oldName); - } - - public void Remove(string path) - { - File.Delete(path); - } - - static readonly string directorySeparator = Path.DirectorySeparatorChar.ToString(); - public string DirectorySeparator => directorySeparator; - - public string GetTempFileName() - { - return Path.GetTempFileName(); - } - - public ILuaIOStream OpenTempFileStream() - { - return new TextLuaIOStream(LuaFileOpenMode.ReadAppend, File.Open(Path.GetTempFileName(), FileMode.Open, FileAccess.ReadWrite)); - } } \ No newline at end of file diff --git a/src/Lua/IO/ILuaIOStream.cs b/src/Lua/IO/ILuaIOStream.cs new file mode 100644 index 00000000..0a3b2240 --- /dev/null +++ b/src/Lua/IO/ILuaIOStream.cs @@ -0,0 +1,28 @@ +namespace Lua.IO +{ + public interface ILuaIOStream : IDisposable + { + public LuaFileOpenMode Mode { get; } + + public LuaFileContentType ContentType { get; } + public ValueTask ReadAllAsync(CancellationToken cancellationToken); + public ValueTask ReadLineAsync(CancellationToken cancellationToken); + public ValueTask ReadStringAsync(int count, CancellationToken cancellationToken); + public ValueTask WriteAsync(LuaFileContent content, CancellationToken cancellationToken); + public ValueTask FlushAsync(CancellationToken cancellationToken); + public void SetVBuf(LuaFileBufferingMode mode, int size); + public long Seek(long offset, SeekOrigin origin); + + public static ILuaIOStream CreateStreamWrapper(Stream stream, LuaFileOpenMode mode, LuaFileContentType contentType = LuaFileContentType.Text) + { + return contentType == LuaFileContentType.Binary + ? new BinaryLuaIOStream(mode, stream) + : new TextLuaIOStream(mode, stream); + } + + public void Close() + { + Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Lua/IO/ILuaStandardIO.cs b/src/Lua/IO/ILuaStandardIO.cs new file mode 100644 index 00000000..10996b16 --- /dev/null +++ b/src/Lua/IO/ILuaStandardIO.cs @@ -0,0 +1,22 @@ +namespace Lua.IO; + +/// +/// Interface for standard IO operations (stdin, stdout, stderr) +/// +public interface ILuaStandardIO +{ + /// + /// Open standard input stream + /// + ILuaIOStream Input { get; } + + /// + /// Open standard output stream + /// + ILuaIOStream Output { get; } + + /// + /// Open standard error stream + /// + ILuaIOStream Error { get; } +} \ No newline at end of file diff --git a/src/Lua/IO/StandardIOStream.cs b/src/Lua/IO/StandardIOStream.cs new file mode 100644 index 00000000..918b911d --- /dev/null +++ b/src/Lua/IO/StandardIOStream.cs @@ -0,0 +1,37 @@ +namespace Lua.IO +{ + /// + /// Wrapper for standard IO streams that prevents closing + /// + internal sealed class StandardIOStream(ILuaIOStream innerStream) : ILuaIOStream + { + public LuaFileOpenMode Mode => innerStream.Mode; + public LuaFileContentType ContentType => innerStream.ContentType; + + public ValueTask ReadAllAsync(CancellationToken cancellationToken) + => innerStream.ReadAllAsync(cancellationToken); + + public ValueTask ReadLineAsync(CancellationToken cancellationToken) + => innerStream.ReadLineAsync(cancellationToken); + + public ValueTask ReadStringAsync(int count, CancellationToken cancellationToken) + => innerStream.ReadStringAsync(count, cancellationToken); + + public ValueTask WriteAsync(LuaFileContent content, CancellationToken cancellationToken) + => innerStream.WriteAsync(content, cancellationToken); + + public ValueTask FlushAsync(CancellationToken cancellationToken) + => innerStream.FlushAsync(cancellationToken); + + public void SetVBuf(LuaFileBufferingMode mode, int size) + => innerStream.SetVBuf(mode, size); + + public long Seek(long offset, SeekOrigin origin) + => innerStream.Seek(offset, origin); + + public void Dispose() + { + throw new IOException("cannot close standard file"); + } + } +} \ No newline at end of file diff --git a/src/Lua/Lua.csproj b/src/Lua/Lua.csproj index 853c8afe..48d3591d 100644 --- a/src/Lua/Lua.csproj +++ b/src/Lua/Lua.csproj @@ -6,7 +6,7 @@ enable enable true - + CS0436 LuaCSharp lua;interpreter diff --git a/src/Lua/LuaState.cs b/src/Lua/LuaState.cs index d8d9db53..05c244f7 100644 --- a/src/Lua/LuaState.cs +++ b/src/Lua/LuaState.cs @@ -4,6 +4,7 @@ using Lua.Internal; using Lua.IO; using Lua.Loaders; +using Lua.Platforms; using Lua.Runtime; using Lua.Standard; using System.Buffers; @@ -36,10 +37,16 @@ public sealed class LuaState public LuaMainThread MainThread => mainThread; public LuaThreadAccess TopLevelAccess => new(mainThread, 0); + + public ILuaPlatform Platform { get; } public ILuaModuleLoader ModuleLoader { get; set; } = FileModuleLoader.Instance; - public ILuaFileSystem FileSystem { get; set; } = Lua.IO.FileSystem.Instance; + public ILuaFileSystem FileSystem => Platform.FileSystem ?? throw new InvalidOperationException("FileSystem is not set. Please set it before using LuaState."); + + public ILuaOperatingSystem OperatingSystem => Platform.OperatingSystem ?? throw new InvalidOperationException("OperatingSystem is not set. Please set it before using LuaState."); + + public ILuaStandardIO StandardIO => Platform.StandardIO; // metatables LuaTable? nilMetatable; @@ -51,16 +58,23 @@ public sealed class LuaState public static LuaState Create() { - return new(); + return Create(LuaPlatform.Default); + } + + public static LuaState Create(ILuaPlatform platform) + { + var state = new LuaState(platform); + return state; } - LuaState() + LuaState(ILuaPlatform platform) { mainThread = new(this); environment = new(); envUpValue = UpValue.Closed(environment); registry[ModuleLibrary.LoadedKeyForRegistry] = new LuaTable(0, 8); registry[ModuleLibrary.PreloadKeyForRegistry] = new LuaTable(0, 8); + Platform = platform; } diff --git a/src/Lua/Platforms/ILuaOperatingSystem.cs b/src/Lua/Platforms/ILuaOperatingSystem.cs new file mode 100644 index 00000000..b68f95c8 --- /dev/null +++ b/src/Lua/Platforms/ILuaOperatingSystem.cs @@ -0,0 +1,32 @@ +namespace Lua.Platforms; + +/// +/// Interface for operating system operations beyond file system +/// +public interface ILuaOperatingSystem +{ + /// + /// Get environment variable value + /// + string? GetEnvironmentVariable(string name); + + /// + /// Exit the application with specified code + /// + void Exit(int exitCode); + + /// + /// Get current process start time for clock calculations + /// + DateTime GetProcessStartTime(); + + /// + /// Get current UTC time + /// + DateTime GetCurrentUtcTime(); + + /// + /// Get local time zone offset from UTC + /// + TimeSpan GetLocalTimeZoneOffset(); +} \ No newline at end of file diff --git a/src/Lua/Platforms/OperatingSystem.cs b/src/Lua/Platforms/OperatingSystem.cs new file mode 100644 index 00000000..aeb728ae --- /dev/null +++ b/src/Lua/Platforms/OperatingSystem.cs @@ -0,0 +1,35 @@ +using System.Diagnostics; + +namespace Lua.Platforms +{ + /// + /// Default implementation of ILuaOperatingSystem + /// + public sealed class OperatingSystem : ILuaOperatingSystem + { + public string? GetEnvironmentVariable(string name) + { + return Environment.GetEnvironmentVariable(name); + } + + public void Exit(int exitCode) + { + Environment.Exit(exitCode); + } + + public DateTime GetProcessStartTime() + { + return Process.GetCurrentProcess().StartTime; + } + + public DateTime GetCurrentUtcTime() + { + return DateTime.UtcNow; + } + + public TimeSpan GetLocalTimeZoneOffset() + { + return TimeZoneInfo.Local.BaseUtcOffset; + } + } +} \ No newline at end of file diff --git a/src/Lua/Standard/BasicLibrary.cs b/src/Lua/Standard/BasicLibrary.cs index 54790427..b1749fa7 100644 --- a/src/Lua/Standard/BasicLibrary.cs +++ b/src/Lua/Standard/BasicLibrary.cs @@ -290,14 +290,20 @@ public async ValueTask PCall(LuaFunctionExecutionContext context, Cancellat public async ValueTask Print(LuaFunctionExecutionContext context, CancellationToken cancellationToken) { + var stdout = context.State.StandardIO.Output; + for (int i = 0; i < context.ArgumentCount; i++) { await context.Arguments[i].CallToStringAsync(context, cancellationToken); - Console.Write(context.Thread.Stack.Pop().Read()); - Console.Write('\t'); + await stdout.WriteAsync(new (context.Thread.Stack.Pop().Read()), cancellationToken); + if (i < context.ArgumentCount - 1) + { + await stdout.WriteAsync( new("\t"), cancellationToken); + } } - Console.WriteLine(); + await stdout.WriteAsync(new("\n"), cancellationToken); + await stdout.FlushAsync(cancellationToken); return context.Return(); } diff --git a/src/Lua/Standard/FileHandle.cs b/src/Lua/Standard/FileHandle.cs index 56659f22..3a6a132d 100644 --- a/src/Lua/Standard/FileHandle.cs +++ b/src/Lua/Standard/FileHandle.cs @@ -46,7 +46,7 @@ static FileHandle() fileHandleMetatable[Metamethods.Index] = IndexMetamethod; } - public FileHandle(Stream stream,LuaFileOpenMode mode, LuaFileContentType type =LuaFileContentType.Text) : this(ILuaIOStream.CreateStreamWrapper( stream,mode,type)) { } + public FileHandle(Stream stream, LuaFileOpenMode mode, LuaFileContentType type = LuaFileContentType.Text) : this(ILuaIOStream.CreateStreamWrapper(stream, mode, type)) { } public FileHandle(ILuaIOStream stream) { @@ -73,6 +73,21 @@ public ValueTask WriteAsync(LuaFileContent content, CancellationToken cancellati return stream.WriteAsync(content, cancellationToken); } + public ValueTask WriteAsync(string content, CancellationToken cancellationToken) + { + return stream.WriteAsync(new(content), cancellationToken); + } + + public ValueTask WriteAsync(ReadOnlyMemory content, CancellationToken cancellationToken) + { + return stream.WriteAsync(new (content), cancellationToken); + } + + public ValueTask WriteAsync(IBinaryData content, CancellationToken cancellationToken) + { + return stream.WriteAsync(new(content), cancellationToken); + } + public long Seek(string whence, long offset) => whence switch { diff --git a/src/Lua/Standard/Internal/IOHelper.cs b/src/Lua/Standard/Internal/IOHelper.cs index 67e00129..3d99e808 100644 --- a/src/Lua/Standard/Internal/IOHelper.cs +++ b/src/Lua/Standard/Internal/IOHelper.cs @@ -42,18 +42,18 @@ public static async ValueTask WriteAsync(FileHandle file, string name, LuaF var arg = context.Arguments[i]; if (arg.TryRead(out var str)) { - await file.WriteAsync(new(str), cancellationToken); + await file.WriteAsync(str, cancellationToken); } else if (arg.TryRead(out var d)) { using var fileBuffer = new PooledArray(64); var span = fileBuffer.AsSpan(); d.TryFormat(span, out var charsWritten); - await file.WriteAsync(new(fileBuffer.UnderlyingArray.AsMemory(0,charsWritten) ), cancellationToken); + await file.WriteAsync(fileBuffer.UnderlyingArray.AsMemory(0,charsWritten) , cancellationToken); } else if (arg.TryRead(out var binaryData)) { - await file.WriteAsync(new (binaryData), cancellationToken); + await file.WriteAsync( binaryData, cancellationToken); } else { diff --git a/src/Lua/Standard/OpenLibsExtensions.cs b/src/Lua/Standard/OpenLibsExtensions.cs index 816f46be..f9a7c404 100644 --- a/src/Lua/Standard/OpenLibsExtensions.cs +++ b/src/Lua/Standard/OpenLibsExtensions.cs @@ -1,6 +1,5 @@ using Lua.IO; using Lua.Runtime; -using Lua.Standard.Internal; namespace Lua.Standard; @@ -48,9 +47,10 @@ public static void OpenIOLibrary(this LuaState state) } var registry = state.Registry; - var stdin = new LuaValue(new FileHandle(ConsoleHelper.OpenStandardInput(),LuaFileOpenMode.Read)); - var stdout = new LuaValue(new FileHandle(ConsoleHelper.OpenStandardOutput(),LuaFileOpenMode.Write)); - var stderr = new LuaValue(new FileHandle( ConsoleHelper.OpenStandardError(),LuaFileOpenMode.Write)); + var standardIO = state.StandardIO; + var stdin = new LuaValue(new FileHandle(standardIO.Input)); + var stdout = new LuaValue(new FileHandle(standardIO.Output)); + var stderr = new LuaValue(new FileHandle(standardIO.Error)); registry["_IO_input"] = stdin; registry["_IO_output"] = stdout; io["stdin"] = stdin; diff --git a/src/Lua/Standard/OperatingSystemLibrary.cs b/src/Lua/Standard/OperatingSystemLibrary.cs index 27894867..ae1ec9e6 100644 --- a/src/Lua/Standard/OperatingSystemLibrary.cs +++ b/src/Lua/Standard/OperatingSystemLibrary.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using Lua.Standard.Internal; namespace Lua.Standard; @@ -11,17 +10,17 @@ public OperatingSystemLibrary() { Functions = [ - new("os","clock", Clock), - new("os","date", Date), - new("os","difftime", DiffTime), - new("os","execute", Execute), - new("os","exit", Exit), - new("os","getenv", GetEnv), - new("os","remove", Remove), - new("os","rename", Rename), - new("os","setlocale", SetLocale), - new("os","time", Time), - new("os","tmpname", TmpName), + new("os", "clock", Clock), + new("os", "date", Date), + new("os", "difftime", DiffTime), + new("os", "execute", Execute), + new("os", "exit", Exit), + new("os", "getenv", GetEnv), + new("os", "remove", Remove), + new("os", "rename", Rename), + new("os", "setlocale", SetLocale), + new("os", "time", Time), + new("os", "tmpname", TmpName), ]; } @@ -29,7 +28,8 @@ public OperatingSystemLibrary() public ValueTask Clock(LuaFunctionExecutionContext context, CancellationToken cancellationToken) { - return new(context.Return(DateTimeHelper.GetUnixTime(DateTime.UtcNow, Process.GetCurrentProcess().StartTime))); + var os = context.State.OperatingSystem; + return new(context.Return(DateTimeHelper.GetUnixTime(os.GetCurrentUtcTime(), os.GetProcessStartTime()))); } public ValueTask Date(LuaFunctionExecutionContext context, CancellationToken cancellationToken) @@ -46,7 +46,7 @@ public ValueTask Date(LuaFunctionExecutionContext context, CancellationToke } else { - now = DateTime.UtcNow; + now = context.State.OperatingSystem.GetCurrentUtcTime(); } var isDst = false; @@ -56,23 +56,25 @@ public ValueTask Date(LuaFunctionExecutionContext context, CancellationToke } else { - now = TimeZoneInfo.ConvertTimeFromUtc(now, TimeZoneInfo.Local); + var offset = context.State.OperatingSystem.GetLocalTimeZoneOffset(); + now = now.Add(offset); isDst = now.IsDaylightSavingTime(); } - if (format == "*t") + if (format is "*t") { - var table = new LuaTable(); - - table["year"] = now.Year; - table["month"] = now.Month; - table["day"] = now.Day; - table["hour"] = now.Hour; - table["min"] = now.Minute; - table["sec"] = now.Second; - table["wday"] = ((int)now.DayOfWeek) + 1; - table["yday"] = now.DayOfYear; - table["isdst"] = isDst; + var table = new LuaTable + { + ["year"] = now.Year, + ["month"] = now.Month, + ["day"] = now.Day, + ["hour"] = now.Hour, + ["min"] = now.Minute, + ["sec"] = now.Second, + ["wday"] = ((int)now.DayOfWeek) + 1, + ["yday"] = now.DayOfYear, + ["isdst"] = isDst + }; return new(context.Return(table)); } @@ -113,11 +115,11 @@ public ValueTask Exit(LuaFunctionExecutionContext context, CancellationToke if (code.TryRead(out var b)) { - Environment.Exit(b ? 0 : 1); + context.State.OperatingSystem.Exit(b ? 0 : 1); } else if (code.TryRead(out var d)) { - Environment.Exit(d); + context.State.OperatingSystem.Exit(d); } else { @@ -126,7 +128,7 @@ public ValueTask Exit(LuaFunctionExecutionContext context, CancellationToke } else { - Environment.Exit(0); + context.State.OperatingSystem.Exit(0); } return new(context.Return()); @@ -135,7 +137,7 @@ public ValueTask Exit(LuaFunctionExecutionContext context, CancellationToke public ValueTask GetEnv(LuaFunctionExecutionContext context, CancellationToken cancellationToken) { var variable = context.GetArgument(0); - return new(context.Return(Environment.GetEnvironmentVariable(variable) ?? LuaValue.Nil)); + return new(context.Return(context.State.OperatingSystem.GetEnvironmentVariable(variable) ?? LuaValue.Nil)); } public ValueTask Remove(LuaFunctionExecutionContext context, CancellationToken cancellationToken) @@ -184,7 +186,7 @@ public ValueTask Time(LuaFunctionExecutionContext context, CancellationToke } else { - return new(context.Return(DateTimeHelper.GetUnixTime(DateTime.UtcNow))); + return new(context.Return(DateTimeHelper.GetUnixTime(context.State.OperatingSystem.GetCurrentUtcTime()))); } } diff --git a/tests/Lua.Tests/AbstractFileTests.cs b/tests/Lua.Tests/AbstractFileTests.cs index 49c99665..718c6521 100644 --- a/tests/Lua.Tests/AbstractFileTests.cs +++ b/tests/Lua.Tests/AbstractFileTests.cs @@ -1,4 +1,5 @@ using Lua.IO; +using Lua.Platforms; using Lua.Standard; using Lua.Tests.Helpers; @@ -26,8 +27,7 @@ public async Task ReadLinesTest() { var fileContent = "line1\nline2\r\nline3"; var fileSystem = new ReadOnlyFileSystem(new() { { "test.txt", fileContent } }); - var state = LuaState.Create(); - state.FileSystem = fileSystem; + var state = LuaState.Create(LuaPlatform.Default with{FileSystem = fileSystem}); state.OpenStandardLibraries(); try { @@ -56,8 +56,7 @@ public async Task ReadFileTest() { var fileContent = "Hello, World!"; var fileSystem = new ReadOnlyFileSystem(new() { { "test.txt", fileContent } }); - var state = LuaState.Create(); - state.FileSystem = fileSystem; + var state = LuaState.Create(LuaPlatform.Default with{FileSystem = fileSystem}); state.OpenStandardLibraries(); await state.DoStringAsync( diff --git a/tests/Lua.Tests/IOTests.cs b/tests/Lua.Tests/IOTests.cs index b1492b76..f8641616 100644 --- a/tests/Lua.Tests/IOTests.cs +++ b/tests/Lua.Tests/IOTests.cs @@ -127,7 +127,7 @@ public async Task BinaryStream_Write_And_Read_Bytes() } [Test] - public async Task TextStream_Cannot_Write_Binary_Content() + public void TextStream_Cannot_Write_Binary_Content() { var testFile = GetTestFilePath("text_binary_mix.txt"); @@ -140,7 +140,7 @@ public async Task TextStream_Cannot_Write_Binary_Content() } [Test] - public async Task BinaryStream_Cannot_Write_Text_Content() + public void BinaryStream_Cannot_Write_Text_Content() { var testFile = GetTestFilePath("binary_text_mix.bin");