I'd like to use a dispatch IO channel to read some data from a file descriptor. After creating the channel, the next step is to call read
, whose declaration is as follows:
func read(offset: off_t,
length: Int,
queue: DispatchQueue,
ioHandler: @escaping (Bool, DispatchData?, Int32) -> Void)
The documentation for the length
parameter says:
The number of bytes to read from the channel. Specify SIZE_MAX to continue reading data until an EOF is reached.
Seems easy enough. In my case, I'd like do just that — read until EOF. So I'll pass SIZE_MAX
:
// `queue` and `handler` defined elsewhere
channel.read(offset: 0, length: SIZE_MAX, queue: queue, ioHandler: handler)
The astute reader has guessed that the compiler doesn't like this:
Cannot convert value of type 'UInt' to expected argument type 'Int'
SIZE_MAX
is of type UInt
, but length
is of type Int
. The compiler offers to fix it:
channel.read(offset: 0, length: Int(SIZE_MAX), queue: queue, ioHandler: handler)
But of course, at runtime, this doesn't work out so well:
fatal error: Not enough bits to represent a signed value
Naturally if SIZE_MAX
is the largest value representable by UInt
, then Int
cannot represent it. After some quick searching, I found this exact issue on the Swift bug tracker. Since it doesn't seem to yet be addressed — and I'm unsure of my ability to address it myself with a pull request — how can I work around this issue? Or am I missing a way to do what I want?
The Swift Stdlib rationales document covers the explicit decision to import size_t
as Int
rather than UInt
. It boils down to "fewer type conversions, and who needs to specify numbers above 2^63 anyways (sorry, 32-bit platforms)." Fair enough, but that doesn't cover issues like mine, where the use of SIZE_MAX
is part of an API.