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?
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.