Browse Source

Add: os.time

AnnulusGames 1 year ago
parent
commit
451e91b00a

+ 1 - 0
src/Lua/Standard/OpenLibExtensions.cs

@@ -87,6 +87,7 @@ public static class OpenLibExtensions
 
     static readonly LuaFunction[] osFunctions = [
         ClockFunction.Instance,
+        TimeFunction.Instance,
     ];
 
     public static void OpenBasicLibrary(this LuaState state)

+ 41 - 0
src/Lua/Standard/OperatingSystem/DateTimeHelper.cs

@@ -1,9 +1,16 @@
 using System.Runtime.CompilerServices;
+using Lua.Runtime;
 
 namespace Lua.Standard.OperatingSystem;
 
 internal static class DateTimeHelper
 {
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public static double GetUnixTime(DateTime dateTime)
+    {
+        return GetUnixTime(dateTime, DateTime.UnixEpoch);
+    }
+
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public static double GetUnixTime(DateTime dateTime, DateTime epoch)
     {
@@ -18,4 +25,38 @@ internal static class DateTimeHelper
         var ts = TimeSpan.FromSeconds(unixTime);
         return DateTime.UnixEpoch + ts;
     }
+
+    public static DateTime ParseTimeTable(LuaState state, LuaTable table)
+    {
+        static int GetTimeField(LuaState state, LuaTable table, string key, bool required = true, int defaultValue = 0)
+        {
+            if (!table.TryGetValue(key, out var value))
+            {
+                if (required)
+                {
+                    throw new LuaRuntimeException(state.GetTraceback(), $"field '{key}' missing in date table");
+                }
+                else
+                {
+                    return defaultValue;
+                }
+            }
+
+            if (value.TryGetNumber(out var d) && MathEx.IsInteger(d))
+            {
+                return (int)d;
+            }
+
+            throw new LuaRuntimeException(state.GetTraceback(), $"field '{key}' is not an integer");
+        }
+
+        var day = GetTimeField(state, table, "day");
+        var month = GetTimeField(state, table, "month");
+        var year = GetTimeField(state, table, "year");
+        var sec = GetTimeField(state, table, "sec", false, 0);
+        var min = GetTimeField(state, table, "min", false, 0);
+        var hour = GetTimeField(state, table, "hour", false, 12);
+
+        return new DateTime(year, month, day, hour, min, sec);
+    }
 }

+ 23 - 0
src/Lua/Standard/OperatingSystem/TimeFunction.cs

@@ -0,0 +1,23 @@
+namespace Lua.Standard.OperatingSystem;
+
+public sealed class TimeFunction : LuaFunction
+{
+    public override string Name => "time";
+    public static readonly TimeFunction Instance = new();
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        if (context.HasArgument(0))
+        {
+            var table = context.GetArgument<LuaTable>(0);
+            var date = DateTimeHelper.ParseTimeTable(context.State, table);
+            buffer.Span[0] = DateTimeHelper.GetUnixTime(date);
+            return new(1);
+        }
+        else
+        {
+            buffer.Span[0] = DateTimeHelper.GetUnixTime(DateTime.UtcNow);
+            return new(1);
+        }
+    }
+}