Swift GCD 覆盖中的类型不匹配

Type mismatch in Swift GCD overlay

我想用一个dispatch IO channel to read some data from a file descriptor. After creating the channel, the next step is to call read,它的声明如下:

func read(offset: off_t, 
   length: Int, 
    queue: DispatchQueue, 
ioHandler: @escaping (Bool, DispatchData?, Int32) -> Void)

length 参数的文档说:

The number of bytes to read from the channel. Specify SIZE_MAX to continue reading data until an EOF is reached.

看起来很简单。就我而言,我想这样做 — 一直读到 EOF。所以我会通过 SIZE_MAX:

// `queue` and `handler` defined elsewhere
channel.read(offset: 0, length: SIZE_MAX, queue: queue, ioHandler: handler)

精明的reader猜到编译器不喜欢这样:

Cannot convert value of type 'UInt' to expected argument type 'Int'

SIZE_MAXUInt 类型,但 lengthInt 类型。编译器提供修复它:

channel.read(offset: 0, length: Int(SIZE_MAX), queue: queue, ioHandler: handler)

当然,在运行时,这并不是很好:

fatal error: Not enough bits to represent a signed value

自然如果SIZE_MAXUInt可以表示的最大值,那么Int就不能表示了。快速搜索后,我找到了 this exact issue on the Swift bug tracker。因为它似乎还没有得到解决——而且我不确定我自己是否有能力通过拉取请求来解决它——我该如何解决这个问题?还是我错过了一种方法来做我想做的事?


Swift Stdlib 基本原理文档 covers the explicit decision to import size_t as Int rather than UInt。它归结为 "fewer type conversions, and who needs to specify numbers above 2^63 anyways (sorry, 32-bit platforms)." 足够公平,但这不包括像我这样的问题,其中 SIZE_MAX 的使用是 API.

的一部分

只需使用 Int.max 如果您在 64 位平台上,您仍然几乎可以保证在读取 Int.max 字节之前到达文件末尾。在 32 位平台上,如果您的文件非常大,您可能需要发出多次读取。

那你应该向Apple报告这个问题。我不确定 Dispatch IO 库是属于 Apple 还是 Swift 开源项目,或者它是否只是一个文档错误。

更新

源代码是开源的,读取操作只是对长度为size_t的C函数的简单包装。

https://github.com/apple/swift-corelibs-libdispatch/blob/master/src/swift/IO.swift

我没试过,但你几乎可以肯定地使用位模式,甚至可能 -1。不过我想我还是会选择 Int.max