49394

What is Swift enum byte representation?

Question:

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 <strong>0x10</strong>, however, it contains <strong>0x02</strong>.

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.

Answer1:

The Swift ABI is still work in progress (expected to be fixed with Swift 4). The way enums are represented in memory <a href="https://github.com/apple/swift/blob/master/docs/ABI/TypeLayout.rst#fragile-enum-layout" rel="nofollow">is described here</a>.

Your case is a <a href="https://github.com/apple/swift/blob/master/docs/ABI.rst#c-like-enums" rel="nofollow">"c-like enum"</a> because is has...

<ul><li>two or more cases</li> <li>no associated values</li> </ul>

Quoting the ABI document:

<blockquote>

the enum is laid out as an integer tag with the minimal number of bits to contain all of the cases. [...] The cases are assigned tag values in declaration order.

</blockquote>

The crucial 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 static tables to convert between instances of Enum and their rawValue (and back).

Here's an example that highlights this characteristic of the ABI:

enum Enum: UInt32 { case A = 0 case B = 0xffffffff // value that does not fit into one byte } assert(sizeof(Enum.self) == 1)

Answer2:

Each enum case is given a standard order value. Which is what you are getting when you don't use .rawValue.

For example, if you change your enum to:

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

Then, when executing

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

data will be 3, because A = 0, B = 1, B2 = 2, C = 3

Recommend

  • Getting Decibels from AVAudioRecorder
  • Detect Internet Connection and display UIAlertview Swift 3
  • Can I use jquery to blank textarea fields or ajax like input boxes?
  • Laravel lmutator $this->attributes return 'Undefined index: id'
  • How to set an entity field that does not exist on the table but does exists in the raw SQL as an ali
  • Generic/Unknown HTTP Error with response code 0 using UnityWebRequest
  • @tailrec why does this method not compile with 'contains a recursive call not in tail position&
  • Count from each distinct date, fill in missing dates with zero
  • Examples of how to a STS in .Net 4.5 using WCF
  • Compare struct to a constant in C
  • Using Generics on right hand side in Java 6?
  • Wrong labels when plotting a time series pandas dataframe with matplotlib
  • SQL Query - Table Joining Problems
  • Salesforce Different WSDL files and when to use
  • android google indoor map
  • Android application: how to use the camera and grab the image bytes?
  • Query to find the duplicates between the name and number in table
  • presentShareDialogWithParams posts to FB wall, but callback handler results say error
  • Zurb Foundation _global.scss meta styles for js?
  • Eloquent update method change created_at timestamp
  • Is there a perl module to validate passwords stored in “{crypt}hashedpassword” “{ssha}hashedpassword
  • Installing Apache MyFaces 2 on WildFly 8.2.0
  • Time complexity of a program which involves multiple variables
  • Checking free space on FTP server
  • Using jQuery closest() method with class selector
  • PHPUnit_Framework_TestCase class is not available. Fix… - Makegood , Eclipse
  • QLineEdit password safety
  • Array.prototype.includes - not transformed with babel
  • How to recover from a Spring Social ExpiredAuthorizationException
  • TFS: Get latest causes slow project reloading
  • ILMerge & Keep Assembly Name
  • Arrow is showed instead of the material design version hamburger icon. Why doesn't syncState in
  • Large data - storage and query
  • Rearranging Cells in UITableView Bug & Saving Changes
  • WOWZA + RTMP + HTML5 Playback?
  • Proper way to use connect-multiparty with express.js?
  • Why can't I rebase on to an ancestor of source changesets if on a different branch?
  • Conditional In-Line CSS for IE and Others?