2

In continuation of my original post: Using Structs (Bytes) with SWIFT - Struct to NSData and NSData to Struct

I'm now finding that if I have a struct with bytes mixes with a byte array it doesn't pack correctly.

Example Code:

struct exampleStruct {
    var ModelNumber: Byte
    var MajorVersion: Byte
    var MinorVersion: Byte
    var Revision: Byte
    var Message: [Byte]
}

var myStruct = exampleStruct (
    ModelNumber: 1,
    MajorVersion: 2,
    MinorVersion: 3,
    Revision: 4,
    Message: [0x48, 0x45, 0x4C, 0x4C, 0x4F] // HELLO
)

println(myStruct.Message) returns correct array with values of [72,69,76,76,79]

However, when I convert this struct to NSData using:

// Struct to NSData.
var data = NSData(
    bytes: & myStruct,
    length: sizeof(exampleStruct)
)

I get unexpected results of: "data: <01020304 00000000 108c91fd a87f0000>". I was expecting "data: <01020304 48454c4c 4f>"

It seems like this is because the [Byte] Array length is not set. Can it be set in SWIFT? When I try the following:

struct exampleStruct {
   var ModelNumber: Byte
   var MajorVersion: Byte
   var MinorVersion: Byte
   var Revision: Byte
   var Message: Byte[5] // << Set array length 5
}

I get a warning that states: "Fixed-length arrays are not yet supported".

Anyway to work around this limitation?

1
  • [Byte] is a Swift struct Array and not a C array. Commented Dec 4, 2014 at 21:11

1 Answer 1

2

var Message: [Byte] declares a variable of the type struct Array:

struct Array<T> : MutableCollectionType, Sliceable {

    /// The type of element stored by this `Array`
    typealias Element = T

    /// Always zero, which is the index of the first element when non-empty.
    var startIndex: Int { get }

    /// A "past-the-end" element index; the successor of the last valid
    /// subscript argument.
    var endIndex: Int { get }
    subscript (index: Int) -> T

    // ... and much more ...
}

so this is not just a "C array" of bytes. The actual storage is opaque and only accessible through methods and properties.

You can define a tuple of fixed size:

struct exampleStruct {
    var ModelNumber: Byte
    var MajorVersion: Byte
    var MinorVersion: Byte
    var Revision: Byte
    var Message: (Byte, Byte, Byte, Byte, Byte)
}

var myStruct = exampleStruct (
    ModelNumber: 1,
    MajorVersion: 2,
    MinorVersion: 3,
    Revision: 4,
    Message: (0x48, 0x45, 0x4C, 0x4C, 0x4F) // HELLO
)
var data = NSData(
    bytes: &myStruct,
    length: sizeof(exampleStruct)
)

println(data) // <01020304 48454c4c 4f>

However, I don't think that Swift makes any guarantees about the binary representation of its structures, so this may break in the future.

Sign up to request clarification or add additional context in comments.

2 Comments

This is great - Thanks! For some reason I keep thinking SWIFT is more similar to C than it actually is.
@Mavro: You are welcome. – If you need a well-defined representation (e.g. for data exchange) then you are probably more on the safe side by defining a C struct and importing that into Swift (or define your own marshaling functions).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.