Sorry I didn’t follow-up here earlier. I’m not entirely sure why I missed this.
I reviewed the code snippets posted above and I don’t think any of them work. Here code that will work:
extension NEFilterFlow {
/// A wrapper around `sourceAppAuditToken` that returns a value of the right type.
///
/// - Note: I’d normally write this code in a much more compact fashion but
/// I’ve expanded it out so that I can comment each step.
var sourceAppAuditTokenQ: audit_token_t? {
// The following lines check whether the `sourceAppAuditToken` value is
// missing, returning `nil` in that case.
//
// The size check is a good idea in general, but it’s particularly
// important because of the way that we set up `pRaw`. See the comments
// below for more details.
guard
let tokenData = self.sourceAppAuditToken,
tokenData.count == MemoryLayout<audit_token_t>.size
else {
return nil
}
// Here we use `withUnsafeBytes(_:)` to call a closure (the stuff inside
// the curly brackets) with an `UnsafeRawBufferPointer` that represents
// the bytes in the `tokenData` value. This `buf` value is, as the type
// name suggests, a way to represent a buffer of raw bytes.
return tokenData.withUnsafeBytes { (buf: UnsafeRawBufferPointer) -> audit_token_t in
// Here we set `pRaw` to a pointer to the base address of that
// buffer. Note the force unwrap (`!`). That’s necessary because
// `buf.baseAddress` is optional, that is, it might be `nil`. That
// can only happen if the buffer is empty. Thus, this force unwrap
// is safe because of the size check that we did earlier.
let pRaw = buf.baseAddress!
// He we convert the raw pointer to a typed pointer. The
// `assumingMemoryBound(to:)` routine is something that you should
// approach with _extreme_ caution. See its doc comments for an
// explanation as to why. In this case, however, its the right
// thing to do, because the framework guarantees that the buffer
// contains an valid `audit_token_t`.
let pToken = pRaw.assumingMemoryBound(to: audit_token_t.self)
// He we dereference our typed pointer to get the actual value.
let result = pToken.pointee
// Finally, we return that value from our closure. This becomes the
// result of the `withUnsafeBytes(_:)` call, which ultimately
// becomes the result of our property getter.
return result
}
}
}
Clearly this is very longwinded, so here’s a version that shows how I might write this in production code:
var sourceAppAuditTokenQ: audit_token_t? {
guard
let tokenData = self.sourceAppAuditToken,
tokenData.count == MemoryLayout<audit_token_t>.size
else { return nil }
return tokenData.withUnsafeBytes { buf in
buf.baseAddress!.assumingMemoryBound(to: audit_token_t.self).pointee
}
}
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"