From 9e145c0143781f6e780f69b495020e93b87738ca Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Sun, 13 Oct 2019 21:59:55 -0400 Subject: [PATCH] Fix issue on Windows with HANDLE being confused with an io opaque handle. This adds an opaque handle type that can then be used without knowing what the underlying OS handle type is. Avoiding a direct alias means the type is distinct for std.io, and can't be confused with other opaque types (as was the case for Windows). Closes #20. --- src/std/io/driver/package.d | 23 ++++++++++++++++------- src/std/io/driver/sync.d | 16 ++++++++-------- src/std/io/file.d | 10 +++++----- src/std/io/net/socket.d | 10 +++++----- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/std/io/driver/package.d b/src/std/io/driver/package.d index f890258..eeec507 100644 --- a/src/std/io/driver/package.d +++ b/src/std/io/driver/package.d @@ -25,6 +25,13 @@ package static assert(0, "unimplemented"); } +/// All handles in std.io are based on this type. The implementation defines how it is used. +struct OpaqueHandle +{ + enum OpaqueHandle INVALID = OpaqueHandle(cast(void*)-1); + void *handle; +} + /** The driver interface used by std.io. @@ -39,16 +46,14 @@ interface Driver { // FILE and SOCKET handles cannot be manipulated in @safe code, so most of // the Driver's API is @safe. -shared @safe @nogc: +@safe @nogc: /** Opaque file handle Interpretation left to driver, typically `int` file descriptor on Posix systems and `HANDLE` on Windows. */ - alias FILE = void*; - /// value used for invalid/closed files - enum INVALID_FILE = cast(void*)-1; + alias FILE = OpaqueHandle; version (Posix) alias tchar = char; /// UTF-8 path on Posix, UTF-16 path on Windows @@ -57,6 +62,7 @@ shared @safe @nogc: else static assert(0, "unimplemented"); + shared { /** Create/open file at `path` in `mode`. @@ -83,6 +89,7 @@ shared @safe @nogc: size_t write(scope FILE f, /*in*/ const scope ubyte[][] bufs); /// seek file to offset ulong seek(scope FILE f, long offset, int whence); + } /** Opaque socket handle @@ -90,9 +97,10 @@ shared @safe @nogc: Interpretation left to driver, typically `int` file descriptor on Posix systems and `SOCKET` on Windows. */ - alias SOCKET = void*; - /// value used for invalid/closed sockets - enum INVALID_SOCKET = cast(void*)-1; + alias SOCKET = OpaqueHandle; + + + shared { /// create socket SOCKET createSocket(AddrFamily family, SocketType type, Protocol protocol); /** @@ -151,6 +159,7 @@ shared @safe @nogc: int resolve( /*in*/ const scope char[] hostname, /*in*/ const scope char[] service, AddrFamily family, SocketType socktype, Protocol protocol, scope int delegate(const scope ref AddrInfo ai) @safe @nogc cb); + } /// @safe @nogc unittest diff --git a/src/std/io/driver/sync.d b/src/std/io/driver/sync.d index 284a915..8cc359a 100644 --- a/src/std/io/driver/sync.d +++ b/src/std/io/driver/sync.d @@ -525,13 +525,13 @@ version (Posix) /// handle to file Driver.FILE h2f(return scope int fd) pure nothrow @trusted @nogc { - return cast(void*) fd; + return Driver.FILE(cast(void*) fd); } /// file to handle int f2h(scope Driver.FILE f) pure nothrow @trusted @nogc { - return cast(int) f; + return cast(int) f.handle; } static assert(int.sizeof <= Driver.SOCKET.sizeof); @@ -539,13 +539,13 @@ version (Posix) /// handle to socket Driver.SOCKET h2s(return scope int fd) pure nothrow @trusted @nogc { - return cast(Driver.SOCKET) fd; + return Driver.SOCKET(cast(void *)fd); } /// socket to handle inout(int) s2h(scope inout Driver.SOCKET s) pure nothrow @trusted @nogc { - return cast(int) s; + return cast(int) s.handle; } } else version (Windows) @@ -557,13 +557,13 @@ else version (Windows) /// handle to file Driver.FILE h2f(return scope HANDLE fd) pure nothrow @trusted @nogc { - return cast(Driver.FILE) fd; + return Driver.FILE(cast(void*)fd); } /// file to handle HANDLE f2h(return scope Driver.FILE f) pure nothrow @trusted @nogc { - return cast(HANDLE) f; + return cast(HANDLE) f.handle; } static assert(ws2.SOCKET.sizeof <= Driver.SOCKET.sizeof); @@ -571,13 +571,13 @@ else version (Windows) /// handle to socket Driver.SOCKET h2s(return scope ws2.SOCKET fd) pure nothrow @trusted @nogc { - return cast(Driver.SOCKET) fd; + return Driver.SOCKET(cast(void *)fd); } /// socket to handle inout(ws2.SOCKET) s2h(scope inout Driver.SOCKET s) pure nothrow @trusted @nogc { - return cast(ws2.SOCKET) s; + return cast(ws2.SOCKET) s.handle; } } diff --git a/src/std/io/file.d b/src/std/io/file.d index c602962..7d14b3b 100644 --- a/src/std/io/file.d +++ b/src/std/io/file.d @@ -189,16 +189,16 @@ struct File /// close the file void close() scope @trusted { - if (f is Driver.INVALID_FILE) + if (f is Driver.FILE.INVALID) return; driver.closeFile(f); - f = Driver.INVALID_FILE; + f = Driver.FILE.INVALID; } /// return whether file is open bool isOpen() const scope { - return f != Driver.INVALID_FILE; + return f != Driver.FILE.INVALID; } /// @@ -353,7 +353,7 @@ struct File File move() return scope nothrow /*pure Issue 18590*/ { auto f = this.f; - this.f = Driver.INVALID_FILE; + this.f = Driver.FILE.INVALID; return File(f); } @@ -367,7 +367,7 @@ private: this.f = f; } - Driver.FILE f = Driver.INVALID_FILE; + Driver.FILE f = Driver.FILE.INVALID; } /// diff --git a/src/std/io/net/socket.d b/src/std/io/net/socket.d index 4669ea8..ac61578 100644 --- a/src/std/io/net/socket.d +++ b/src/std/io/net/socket.d @@ -127,16 +127,16 @@ struct Socket /// close the socket void close() @trusted { - if (s == Driver.INVALID_SOCKET) + if (s == Driver.SOCKET.INVALID) return; driver.closeSocket(s); - s = Driver.INVALID_SOCKET; + s = Driver.SOCKET.INVALID; } /// return whether the socket is open bool isOpen() const pure nothrow { - return s != Driver.INVALID_SOCKET; + return s != Driver.SOCKET.INVALID; } /// @@ -552,7 +552,7 @@ struct Socket Socket move() return scope nothrow /*pure Issue 18590*/ { auto s = this.s; - this.s = Driver.INVALID_SOCKET; + this.s = Driver.SOCKET.INVALID; return Socket(s); } @@ -611,5 +611,5 @@ private: this.s = s; } - Driver.SOCKET s = Driver.INVALID_SOCKET; + Driver.SOCKET s = Driver.SOCKET.INVALID; }