@@ -220,20 +220,19 @@ struct FileHandle: ~Copyable, Sendable {
220220 _closeWhenDone = closeWhenDone
221221 }
222222
223- /// Initialize an instance of this type with an existing POSIX file descriptor
224- /// for reading.
223+ /// Initialize an instance of this type with an existing POSIX file descriptor.
225224 ///
226225 /// - Parameters:
227226 /// - fd: The POSIX file descriptor to wrap. The caller is responsible for
228- /// ensuring that this file handle is open in the expected mode and that
229- /// another part of the system won't close it.
227+ /// ensuring that this file descriptor is open in the expected mode and
228+ /// that another part of the system won't close it.
230229 /// - options: The options `fd` was opened with.
231230 ///
232231 /// - Throws: Any error preventing the stream from being opened.
233232 ///
234233 /// The resulting file handle takes ownership of `fd` and closes it when it is
235234 /// deinitialized or if an error is thrown from this initializer.
236- init ( unsafePOSIXFileDescriptor fd: CInt , options: OpenOptions ) throws {
235+ init ( unsafePOSIXFileDescriptor fd: consuming CInt , options: OpenOptions ) throws {
237236#if os(Windows)
238237 let fileHandle = _fdopen ( fd, options. stringValue)
239238#else
@@ -290,7 +289,7 @@ struct FileHandle: ~Copyable, Sendable {
290289 ///
291290 /// Use this function when calling C I/O interfaces such as `fputs()` on the
292291 /// underlying C file handle.
293- borrowing func withUnsafeCFILEHandle< R> ( _ body: ( SWT_FILEHandle ) throws -> R ) rethrows -> R {
292+ borrowing func withUnsafeCFILEHandle< R> ( _ body: ( borrowing SWT_FILEHandle ) throws -> R ) rethrows -> R {
294293 try body ( _fileHandle)
295294 }
296295
@@ -307,7 +306,7 @@ struct FileHandle: ~Copyable, Sendable {
307306 /// that require a file descriptor instead of the standard `FILE *`
308307 /// representation. If the file handle cannot be converted to a file
309308 /// descriptor, `nil` is passed to `body`.
310- borrowing func withUnsafePOSIXFileDescriptor< R> ( _ body: ( CInt ? ) throws -> R ) rethrows -> R {
309+ borrowing func withUnsafePOSIXFileDescriptor< R> ( _ body: ( borrowing CInt ? ) throws -> R ) rethrows -> R {
311310 try withUnsafeCFILEHandle { handle in
312311#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI)
313312 let fd = fileno ( handle)
@@ -326,6 +325,44 @@ struct FileHandle: ~Copyable, Sendable {
326325 }
327326
328327#if os(Windows)
328+ /// Initialize an instance of this type with an existing Windows file handle.
329+ ///
330+ /// - Parameters:
331+ /// - handle: The Windows file handle to wrap. The caller is responsible for
332+ /// ensuring that this file handle is open in the expected mode and that
333+ /// another part of the system won't close it.
334+ /// - options: The options `handle` was opened with.
335+ ///
336+ /// - Throws: Any error preventing the stream from being opened.
337+ ///
338+ /// The resulting file handle takes ownership of `handle` and closes it when
339+ /// it is deinitialized or if an error is thrown from this initializer.
340+ init ( unsafeWindowsHANDLE handle: consuming HANDLE , options: OpenOptions ) throws {
341+ var flags : CInt = _O_BINARY
342+ switch ( options. contains ( . readAccess) , options. contains ( . writeAccess) ) {
343+ case ( true , true ) :
344+ flags |= _O_RDWR
345+ case ( true , false ) :
346+ flags |= _O_RDONLY
347+ case ( false , true ) :
348+ flags |= _O_WRONLY
349+ case ( false , false ) :
350+ break
351+ }
352+ if !options. contains ( . inheritedByChild) {
353+ flags |= _O_NOINHERIT
354+ }
355+
356+ let fd = _open_osfhandle ( Int ( bitPattern: handle) , flags)
357+ guard fd >= 0 else {
358+ let errorCode = swt_errno ( )
359+ _ = CloseHandle ( handle)
360+ throw CError ( rawValue: errorCode)
361+ }
362+
363+ try self . init ( unsafePOSIXFileDescriptor: fd, options: options)
364+ }
365+
329366 /// Call a function and pass the underlying Windows file handle to it.
330367 ///
331368 /// - Parameters:
@@ -339,7 +376,7 @@ struct FileHandle: ~Copyable, Sendable {
339376 /// that require the file's `HANDLE` representation instead of the standard
340377 /// `FILE *` representation. If the file handle cannot be converted to a
341378 /// Windows handle, `nil` is passed to `body`.
342- borrowing func withUnsafeWindowsHANDLE< R> ( _ body: ( HANDLE ? ) throws -> R ) rethrows -> R {
379+ borrowing func withUnsafeWindowsHANDLE< R> ( _ body: ( borrowing HANDLE ? ) throws -> R ) rethrows -> R {
343380 try withUnsafePOSIXFileDescriptor { fd in
344381 guard let fd else {
345382 return try body ( nil )
0 commit comments