Werolik Werolik - 4 months ago 28
Swift Question

What is Swift enum byte representation?

I have the following enum:

enum Enum: UInt8
{
case A = 0x00
case B = 0x01
case C = 0x10
}


I use the following code to convert it to
NSData
:

var value = Enum.C
let data = NSData(bytes: &value, length: 1)


Naturally, I expect
data
to contain
0x10
, however, it contains
0x02
.

For
Enum.A
it contains
0x00
and for
Enum.B
it contains
0x01
.

To me, it looks like it stores an index of the value instead of its actual raw data. Could someone explain this behavior?

P.S. If I use
rawValue
it works perfectly. However, I want to understand the reason behind, since because of it I cannot create a generic function to convert values to NSData.

Answer

The Swift ABI is still work in progress (expected to be fixed with Swift 4). The way enums are to be represented in memory is described here.

The case you have is a "c-like enum" (more than one case, integer rawValue, no associated values). So:

the enum is laid out as an integer tag with the minimal number of bits to contain all of the cases.

The crucial piece of information here is the "minimal number of bits". This means that (for your case) instances should fit into two bits (as you have three cases). The rawValue 0x10 would need five bits which would be in conflict with the ABI.

The compiler probably uses a static table to convert between instances of Enum and their rawValue.

Comments