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");