There are a bunch of problems here. The confusing error you’re seeing is likely due to poor compiler diagnostics. There’s some sort of compile error within the the various closures in play, and because they are single line closures, and thus involved in type inference, you get a wacky error. I’ve seen this many times before and, to my shame, haven’t yet filed a bug about it )-:
However, there are a much bigger issues with the approach you’ve outlined. First up, Swift does not provide any guarantees about the layout of structs, and thus it’s not safe to declare PacketHeader
in Swift and then access the packet’s bytes via that structure.
If you want to use the struct approach, you’ll need to declare the struct in C and import that struct into Swift. C does provide some limited guarantees about struct layout, and Swift will honour those.
However, there’s a second problem that suggests that this isn’t the right approach, namely that Data
does not guarantee any alignment. If the base address of the buffer ($0
in your example) was misaligned, you could run into problems accessing packetLength
.
I write a lot of networking code and I’ve long since given up on the entire notion of declaring a struct that maps on to a packet. Rather, I treat parsing packets like parsing strings: I start at the front and deal with them byte-wise. For example:
extension Data {
mutating func parseLEUInt32() -> UInt32? {
guard self.count >= 4 else { return nil }
defer {
self = self.dropFirst(4)
}
return self.prefix(4).reversed().reduce(0) { $0 << 8 | UInt32($1) }
}
mutating func parsePacketHeader() -> PacketHeader? {
guard
let packetType = self.parseLEUInt32(),
let packetLength = self.parseLEUInt32()
else { return nil }
return PacketHeader(packetType: packetType, packetLength: packetLength)
}
}
var d = Data([0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef])
let header = d.parsePacketHeader()!
print(String(header.packetType, radix: 16)) // 67452301
print(String(header.packetLength, radix: 16)) // efcdab89
print(d.count) // 0
Note Here I’m extended Data
just for brevity, but in real code I tend to define a custom type to help with this parsing.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple