swiftstructunsafe-pointers

How to read bytes of struct in Swift


I am working with a variety of structs in Swift that I need to be able to look at the memory of directly.

How can I look at a struct byte for byte?

For example:

struct AwesomeStructure {
  var index: Int32
  var id: UInt16
  var stuff: UInt8
  // etc.
}

The compiler will not allow me to do this:

func scopeOfAwesomeStruct() {
    withUnsafePointer(to: &self, { (ptr: UnsafePointer<Int8>) in
    })
}

Obviously because withUnsafePointer is a templated function that requires the UnsafePointer to be the same type as self.

So, how can I break down self (my structs) into 8 bit pieces? Yes, I want to be able to look at index in 4, 8-bit pieces, and so-on.

(In this case, I'm trying to port a CRC algorithm from C#, but I have been confounded by this problem for other reasons as well.)


Solution

  • You can use withUnsafeBytes(_:) directly like this:

    mutating func scopeOfAwesomeStruct() {
        withUnsafeBytes(of: &self) {rbp in
            let ptr = rbp.baseAddress!.assumingMemoryBound(to: UInt8.self)
            //...
        }
    }
    

    As already noted, do not export ptr outside of the closure.

    And it is not safe even if you have a function that knows the length of the structure. Swift API stability is not declared yet. Any of the layout details of structs are not guaranteed, including the orders of the properties and how they put paddings. Which may be different than the C# structs and may generate the different result than that of C#.

    I (and many other developers) believe and expect that the current layout strategy would not change in the near future, so I would write some code like yours. But I do not think it's safe. Remember Swift is not C.

    (Though, it's all the same if you copy the contents of a struct into a Data.)

    If you want a strictly exact layout with C, you can write a C struct and import it into your Swift project.