Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/Lua/IO/ConsoleStandardIO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Lua.Standard.Internal;

namespace Lua.IO;

/// <summary>
/// Default implementation of ILuaStandardIO using Console
/// </summary>
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));
}
103 changes: 103 additions & 0 deletions src/Lua/IO/FileSystem.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
134 changes: 1 addition & 133 deletions src/Lua/IO/ILuaFileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using Lua.Internal;
using System.Text;

namespace Lua.IO;
namespace Lua.IO;

public interface ILuaFileSystem
{
Expand All @@ -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<LuaFileContent> ReadAllAsync(CancellationToken cancellationToken);
public ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken);
public ValueTask<string?> 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));
}
}
28 changes: 28 additions & 0 deletions src/Lua/IO/ILuaIOStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Lua.IO
{
public interface ILuaIOStream : IDisposable
{
public LuaFileOpenMode Mode { get; }

public LuaFileContentType ContentType { get; }
public ValueTask<LuaFileContent> ReadAllAsync(CancellationToken cancellationToken);
public ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken);
public ValueTask<string?> 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();
}
}
}
22 changes: 22 additions & 0 deletions src/Lua/IO/ILuaStandardIO.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Lua.IO;

/// <summary>
/// Interface for standard IO operations (stdin, stdout, stderr)
/// </summary>
public interface ILuaStandardIO
{
/// <summary>
/// Open standard input stream
/// </summary>
ILuaIOStream Input { get; }

/// <summary>
/// Open standard output stream
/// </summary>
ILuaIOStream Output { get; }

/// <summary>
/// Open standard error stream
/// </summary>
ILuaIOStream Error { get; }
}
37 changes: 37 additions & 0 deletions src/Lua/IO/StandardIOStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace Lua.IO
{
/// <summary>
/// Wrapper for standard IO streams that prevents closing
/// </summary>
internal sealed class StandardIOStream(ILuaIOStream innerStream) : ILuaIOStream
{
public LuaFileOpenMode Mode => innerStream.Mode;
public LuaFileContentType ContentType => innerStream.ContentType;

public ValueTask<LuaFileContent> ReadAllAsync(CancellationToken cancellationToken)
=> innerStream.ReadAllAsync(cancellationToken);

public ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken)
=> innerStream.ReadLineAsync(cancellationToken);

public ValueTask<string?> 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");
}
}
}
2 changes: 1 addition & 1 deletion src/Lua/Lua.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

<NoWarn>CS0436</NoWarn>
<!-- NuGet Packaging -->
<PackageId>LuaCSharp</PackageId>
<PackageTags>lua;interpreter</PackageTags>
Expand Down
Loading