When designing APIs that deal with byte-level data, is there a good reason to use Data
as a buffer instead of [UInt8]
?
From what I understand, Arrays of trivial types like UInt8
are always stored contiguously in memory. But I also know even SwiftNIO
uses its own ByteBuffer
type instead of [UInt8]
. What do these buffer types do differently, and am I giving up on valuable performance or safety by simply using [UInt8]
?
When designing APIs that deal with byte-level data, is there a good reason to use
Data
as a buffer instead of[UInt8]
?
There is no simple answer to this. Data
has a lot of history, and that’s both good and bad. On the plus side, it’s well integrated, both into Swift itself and, especially, into Apple platforms. On the minus side, that history results in various oddities.
A lot of folks avoid Data
because they want to avoid Foundation. IMO that’s not a good reason. On Apple platforms Foundation is omnipresent. Foundation is also available for non-Apple platforms and, while it’s does have its issues there, basic stuff like Data
works just fine.
SwiftNIO’s ByteBuffer
is reminiscent of Data
but it hits a different design point, one that was specifically crafted to meet SwiftNIO’s requirements. If you want to learn more about that, I second Matt’s recommendation to ask about it on Swift Forums.
Personally, I use both Data
and [UInt8]
depending on the situation:
-
I generally lean towards
Data
because its features make my life easier. Examples of this include reading from and writing to disk, text encodings, and integration with higher-level frameworks. -
In some situations
[UInt8]
is actually easier thanData
. For example, if you’re calling a C API that works with pointers toUInt8
, having a[UInt8]
on the Swift side means that you can take advantage of Swift’s array-to-pointer integration. For more on that, see The Peril of the Ampersand.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"