Make FileStream small enough to fit into an InterfaceProxy.

This commit is contained in:
Sönke Ludwig 2016-12-26 21:28:36 +01:00
parent 003331cc90
commit 35a94412d0
2 changed files with 27 additions and 20 deletions

View file

@ -381,20 +381,25 @@ enum FileMode {
struct FileStream { struct FileStream {
@safe: @safe:
private struct CTX {
Path path;
ulong size;
FileMode mode;
ulong ptr;
}
private { private {
FileFD m_fd; FileFD m_fd;
Path m_path; CTX* m_ctx;
ulong m_size;
FileMode m_mode;
ulong m_ptr;
} }
this(FileFD fd, Path path, FileMode mode) this(FileFD fd, Path path, FileMode mode)
{ {
m_fd = fd; m_fd = fd;
m_path = path; m_ctx = new CTX; // TODO: use FD custom storage
m_mode = mode; m_ctx.path = path;
m_size = eventDriver.files.getSize(fd); m_ctx.mode = mode;
m_ctx.size = eventDriver.files.getSize(fd);
} }
this(this) this(this)
@ -412,13 +417,13 @@ struct FileStream {
@property int fd() { return m_fd; } @property int fd() { return m_fd; }
/// The path of the file. /// The path of the file.
@property Path path() const { return m_path; } @property Path path() const { return ctx.path; }
/// Determines if the file stream is still open /// Determines if the file stream is still open
@property bool isOpen() const { return m_fd != FileFD.invalid; } @property bool isOpen() const { return m_fd != FileFD.invalid; }
@property ulong size() const nothrow { return m_size; } @property ulong size() const nothrow { return ctx.size; }
@property bool readable() const nothrow { return m_mode != FileMode.append; } @property bool readable() const nothrow { return ctx.mode != FileMode.append; }
@property bool writable() const nothrow { return m_mode != FileMode.read; } @property bool writable() const nothrow { return ctx.mode != FileMode.read; }
bool opCast(T)() if (is (T == bool)) { return m_fd != FileFD.invalid; } bool opCast(T)() if (is (T == bool)) { return m_fd != FileFD.invalid; }
@ -429,10 +434,10 @@ struct FileStream {
void seek(ulong offset) void seek(ulong offset)
{ {
m_ptr = offset; ctx.ptr = offset;
} }
ulong tell() nothrow { return m_ptr; } ulong tell() nothrow { return ctx.ptr; }
/// Closes the file handle. /// Closes the file handle.
void close() void close()
@ -444,8 +449,8 @@ struct FileStream {
} }
} }
@property bool empty() const { assert(this.readable); return m_ptr >= m_size; } @property bool empty() const { assert(this.readable); return ctx.ptr >= ctx.size; }
@property ulong leastSize() const { assert(this.readable); return m_size - m_ptr; } @property ulong leastSize() const { assert(this.readable); return ctx.size - ctx.ptr; }
@property bool dataAvailableForRead() { return true; } @property bool dataAvailableForRead() { return true; }
const(ubyte)[] peek() const(ubyte)[] peek()
@ -456,7 +461,7 @@ struct FileStream {
void read(ubyte[] dst) void read(ubyte[] dst)
{ {
auto res = asyncAwait!(FileIOCallback, auto res = asyncAwait!(FileIOCallback,
cb => eventDriver.files.read(m_fd, m_ptr, dst, cb), cb => eventDriver.files.read(m_fd, ctx.ptr, dst, cb),
cb => eventDriver.files.cancelRead(m_fd) cb => eventDriver.files.cancelRead(m_fd)
); );
enforce(res[1] == IOStatus.ok, "Failed to read data from disk."); enforce(res[1] == IOStatus.ok, "Failed to read data from disk.");
@ -465,12 +470,12 @@ struct FileStream {
void write(in ubyte[] bytes) void write(in ubyte[] bytes)
{ {
auto res = asyncAwait!(FileIOCallback, auto res = asyncAwait!(FileIOCallback,
cb => eventDriver.files.write(m_fd, m_ptr, bytes, cb), cb => eventDriver.files.write(m_fd, ctx.ptr, bytes, cb),
cb => eventDriver.files.cancelWrite(m_fd) cb => eventDriver.files.cancelWrite(m_fd)
); );
m_ptr += res[2]; ctx.ptr += res[2];
logDebug("Written %s", res[2]); logDebug("Written %s", res[2]);
if (m_ptr > m_size) m_size = m_ptr; if (ctx.ptr > ctx.size) ctx.size = ctx.ptr;
enforce(res[1] == IOStatus.ok, "Failed to read data from disk."); enforce(res[1] == IOStatus.ok, "Failed to read data from disk.");
} }
@ -494,6 +499,8 @@ logDebug("Written %s", res[2]);
{ {
flush(); flush();
} }
private inout(CTX)* ctx() inout nothrow { return m_ctx; }
} }
mixin validateRandomAccessStream!FileStream; mixin validateRandomAccessStream!FileStream;

View file

@ -76,7 +76,7 @@ struct InterfaceProxy(I) if (is(I == interface)) {
this(O)(O object) @trusted this(O)(O object) @trusted
{ {
static assert(O.sizeof <= m_value.length, "Object is too big to be stored in an InterfaceProxy."); static assert(O.sizeof <= m_value.length, "Object ("~O.stringof~") is too big to be stored in an InterfaceProxy.");
import std.conv : emplace; import std.conv : emplace;
m_intf = ProxyImpl!O.get(); m_intf = ProxyImpl!O.get();
emplace!O(m_value[0 .. O.sizeof]); emplace!O(m_value[0 .. O.sizeof]);