Browse Source

Change: LuaUserData -> ILuaUserData

AnnulusGames 1 year ago
parent
commit
cd7a7dd385

+ 2 - 2
src/Lua/LuaState.cs

@@ -109,7 +109,7 @@ public sealed class LuaState
             LuaValueType.Number => numberMetatable,
             LuaValueType.Function => functionMetatable,
             LuaValueType.Thread => threadMetatable,
-            LuaValueType.UserData => value.UnsafeRead<LuaUserData>().Metatable,
+            LuaValueType.UserData => value.UnsafeRead<ILuaUserData>().Metatable,
             LuaValueType.Table => value.UnsafeRead<LuaTable>().Metatable,
             _ => null
         };
@@ -141,7 +141,7 @@ public sealed class LuaState
                 threadMetatable = metatable;
                 break;
             case LuaValueType.UserData:
-                value.UnsafeRead<LuaUserData>().Metatable = metatable;
+                value.UnsafeRead<ILuaUserData>().Metatable = metatable;
                 break;
             case LuaValueType.Table:
                 value.UnsafeRead<LuaTable>().Metatable = metatable;

+ 2 - 7
src/Lua/LuaUserData.cs

@@ -1,11 +1,6 @@
 namespace Lua;
 
-public abstract class LuaUserData
+public interface ILuaUserData
 {
-    public LuaTable? Metatable { get; set; }
-}
-
-public class LuaUserData<T>(T value) : LuaUserData
-{
-    public T Value { get; } = value;
+    LuaTable? Metatable { get; set; }
 }

+ 9 - 0
src/Lua/LuaUserDataExtensions.cs

@@ -0,0 +1,9 @@
+namespace Lua;
+
+public static class LuaUserDataExtensions
+{
+    public static LuaValue AsLuaValue(this ILuaUserData userData)
+    {
+        return new(userData);
+    }
+}

+ 2 - 7
src/Lua/LuaValue.cs

@@ -167,7 +167,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
                     break;
                 }
             case LuaValueType.UserData:
-                if (t == typeof(LuaUserData) || t.IsSubclassOf(typeof(LuaUserData)))
+                if (t == typeof(ILuaUserData) || typeof(ILuaUserData).IsAssignableFrom(t))
                 {
                     var v = referenceValue!;
                     result = Unsafe.As<object, T>(ref v);
@@ -283,7 +283,7 @@ public readonly struct LuaValue : IEquatable<LuaValue>
         referenceValue = value;
     }
 
-    public LuaValue(LuaUserData value)
+    public LuaValue(ILuaUserData value)
     {
         type = LuaValueType.UserData;
         referenceValue = value;
@@ -319,11 +319,6 @@ public readonly struct LuaValue : IEquatable<LuaValue>
         return new(value);
     }
 
-    public static implicit operator LuaValue(LuaUserData value)
-    {
-        return new(value);
-    }
-
     public override int GetHashCode()
     {
         return HashCode.Combine(type, value, referenceValue);

+ 4 - 3
src/Lua/Standard/FileHandle.cs

@@ -5,7 +5,7 @@ namespace Lua.Standard;
 
 // TODO: optimize (remove StreamReader/Writer)
 
-public class FileHandle : LuaUserData
+public class FileHandle : ILuaUserData
 {
     public static readonly LuaFunction IndexMetamethod = new("index", (context, buffer, ct) =>
     {
@@ -41,7 +41,9 @@ public class FileHandle : LuaUserData
 
     public bool IsClosed => Volatile.Read(ref isClosed);
 
-    static readonly LuaTable fileHandleMetatable;
+    LuaTable? ILuaUserData.Metatable { get => fileHandleMetatable; set => fileHandleMetatable = value; }
+
+    static LuaTable? fileHandleMetatable;
 
     static FileHandle()
     {
@@ -54,7 +56,6 @@ public class FileHandle : LuaUserData
         this.stream = stream;
         if (stream.CanRead) reader = new StreamReader(stream);
         if (stream.CanWrite) writer = new StreamWriter(stream);
-        Metatable = fileHandleMetatable;
     }
 
     public string? ReadLine()

+ 11 - 11
src/Lua/Standard/IOLibrary.cs

@@ -13,9 +13,9 @@ public static class IOLibrary
             io[func.Name] = func;
         }
 
-        io["stdio"] = new FileHandle(Console.OpenStandardInput());
-        io["stdout"] = new FileHandle(Console.OpenStandardOutput());
-        io["stderr"] = new FileHandle(Console.OpenStandardError());
+        io["stdio"] = new FileHandle(Console.OpenStandardInput()).AsLuaValue();
+        io["stdout"] = new FileHandle(Console.OpenStandardOutput()).AsLuaValue();
+        io["stderr"] = new FileHandle(Console.OpenStandardError()).AsLuaValue();
 
         state.Environment["io"] = io;
         state.LoadedModules["io"] = io;
@@ -86,16 +86,16 @@ public static class IOLibrary
         var arg = context.Arguments[0];
         if (arg.TryRead<FileHandle>(out var file))
         {
-            io["stdio"] = file;
-            buffer.Span[0] = file;
+            io["stdio"] = file.AsLuaValue();
+            buffer.Span[0] = file.AsLuaValue();
             return new(1);
         }
         else
         {
             var stream = File.Open(arg.ToString()!, FileMode.Open, FileAccess.ReadWrite);
             var handle = new FileHandle(stream);
-            io["stdio"] = handle;
-            buffer.Span[0] = handle;
+            io["stdio"] = handle.AsLuaValue();
+            buffer.Span[0] = handle.AsLuaValue();
             return new(1);
         }
     }
@@ -164,16 +164,16 @@ public static class IOLibrary
         var arg = context.Arguments[0];
         if (arg.TryRead<FileHandle>(out var file))
         {
-            io["stdout"] = file;
-            buffer.Span[0] = file;
+            io["stdout"] = file.AsLuaValue();
+            buffer.Span[0] = file.AsLuaValue();
             return new(1);
         }
         else
         {
             var stream = File.Open(arg.ToString()!, FileMode.Open, FileAccess.ReadWrite);
             var handle = new FileHandle(stream);
-            io["stdout"] = handle;
-            buffer.Span[0] = handle;
+            io["stdout"] = handle.AsLuaValue();
+            buffer.Span[0] = handle.AsLuaValue();
             return new(1);
         }
     }

+ 2 - 2
src/Lua/Standard/Internal/IOHelper.cs

@@ -25,7 +25,7 @@ internal static class IOHelper
         try
         {
             var stream = File.Open(fileName, fileMode, fileAccess);
-            buffer.Span[0] = new FileHandle(stream);
+            buffer.Span[0] = new FileHandle(stream).AsLuaValue();
             return 1;
         }
         catch (IOException ex)
@@ -76,7 +76,7 @@ internal static class IOHelper
             return 3;
         }
 
-        buffer.Span[0] = file;
+        buffer.Span[0] = file.AsLuaValue();
         return 1;
     }
 

+ 10 - 3
src/Lua/Standard/MathematicsLibrary.cs

@@ -4,7 +4,7 @@ public static class MathematicsLibrary
 {
     public static void OpenMathLibrary(this LuaState state)
     {
-        state.Environment[RandomInstanceKey] = new LuaUserData<Random>(new Random());
+        state.Environment[RandomInstanceKey] = new RandomUserData(new Random()).AsLuaValue();
 
         var math = new LuaTable(0, Functions.Length);
         foreach (var func in Functions)
@@ -51,6 +51,13 @@ public static class MathematicsLibrary
         new("tanh", Tanh),
     ];
 
+    sealed class RandomUserData(Random random) : ILuaUserData
+    {
+        static LuaTable? SharedMetatable;
+        public LuaTable? Metatable { get => SharedMetatable; set => SharedMetatable = value; }
+        public Random Random { get; } = random;
+    }
+
     public static ValueTask<int> Abs(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
@@ -227,7 +234,7 @@ public static class MathematicsLibrary
 
     public static ValueTask<int> Random(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
-        var rand = context.State.Environment[RandomInstanceKey].Read<LuaUserData<Random>>().Value;
+        var rand = context.State.Environment[RandomInstanceKey].Read<RandomUserData>().Random;
 
         if (context.ArgumentCount == 0)
         {
@@ -251,7 +258,7 @@ public static class MathematicsLibrary
     public static ValueTask<int> RandomSeed(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
     {
         var arg0 = context.GetArgument<double>(0);
-        context.State.Environment[RandomInstanceKey] = new LuaUserData<Random>(new Random((int)BitConverter.DoubleToInt64Bits(arg0)));
+        context.State.Environment[RandomInstanceKey] = new RandomUserData(new Random((int)BitConverter.DoubleToInt64Bits(arg0))).AsLuaValue();
         return new(0);
     }