swiftswift-nio

Is it safe to transform a struct directly to Data


The lcl-ping library on GitHub has the following definition of an ICMPHeader struct:

internal struct ICMPHeader {
    /// ICMP message type (ECHO_REQUEST)
    let type: UInt8
    let code: UInt8
    var checkSum: UInt16

    /// the packet identifier
    let idenifier: UInt16

    /// the packet sequence number
    let sequenceNum: UInt16

    /// the ICMP header payload
    var payload: ICMPRequestPayload
}

struct ICMPRequestPayload: Hashable {
    let timestamp: TimeInterval
    let identifier: UInt16
}

and an extension to turn that struct into Data:

extension ICMPPingClient.ICMPHeader {
    var data: Data {
        var payload = self
        return Data(bytes: &payload, count: sizeof(ICMPPingClient.ICMPHeader.self))
    }
}

The extension is used to output the data on a SwiftNIO channel.

Why does this work? And maybe more importantly is this safe? If it's not what would be a situation where this will break?


Solution

  • In a word, no. The code you posted copies the bytes of the internal representation of the structure into Data.

    If you only hold that locally in memory then it might be safe, but if you send it over the network, or save it, you run the risk of compatibility issues. The way a structure is mapped into memory is not guaranteed to be stable across language versions, OS versions, processors, or platforms. Things like the memory size, byte ordering, and word alignment of the values can change without warning.

    If you're looking to see the in-memory representation of a structure then the code you show would be useful. In most other cases it makes more sense to use some sort of platform-independent data serialization.