Errors When Update Code to Avoid Deprecation Warnings Withunsafemutablebytes in Swift 5

Errors when update code to avoid deprecation warnings withUnsafeMutableBytes in swift 5

I wouldn't use Data here – Data represents an untyped collection of "raw" bytes, however crypto_generichash_keygen wants a mutable pointer to typed memory. The reason why the UnsafeMutablePointer<T> variant of withUnsafeMutableBytes was deprecated is that it's fundamentally the wrong abstraction to be providing on untyped memory.

The simplest way to get a buffer of typed memory in Swift is with an Array:

var k = [UInt8](repeating: 0, count: crypto_generichash_keybytes())
flutter_sodium.crypto_generichash_keygen(&k)

You can always turn the resulting buffer into a Data value afterwards by saying Data(k).

Another option is to use an UnsafeMutableBufferPointer:

let k = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: crypto_generichash_keybytes())
defer {
k.deallocate()
}
flutter_sodium.crypto_generichash_keygen(k.baseAddress!)
// Now use the buffer `k` – just make sure you finish using it before the end of
// the scope when `deallocate()` gets called!

Unlike Array, this avoids having to pre-fill the resulting buffer with zeros before being passed off to the C API, however this likely isn't of concern. But just like Array, you can turn such a buffer into a Data by just saying Data(k).


For cases where you get handed a Data value from some external source and need to pass it off to an API as a typed pointer, the simplest and safest option is to just turn it into an array before passing it by saying Array(someData).

For example:

let args = call.arguments as! NSDictionary
let server_pk = (args["server_pk"] as! FlutterStandardTypedData).data
let server_sk = (args["server_sk"] as! FlutterStandardTypedData).data
let client_pk = (args["client_pk"] as! FlutterStandardTypedData).data

var rx = [UInt8](repeating: 0, count: flutter_sodium.crypto_kx_sessionkeybytes())
var tx = [UInt8](repeating: 0, count: flutter_sodium.crypto_kx_sessionkeybytes())

flutter_sodium.crypto_kx_server_session_keys(
&rx, &tx, Array(server_pk), Array(server_sk), Array(client_pk)
)

You probably could use withUnsafeBytes and call bindMemory on the underlying pointer, but I would discourage it, as it changes the type of the underlying memory which could subtly impact the soundness of any other Swift code sharing that memory due to the fact that you're switching out the type from under it.

Swift 5.0: 'withUnsafeBytes' is deprecated: use `withUnsafeBytesR(...)

In Swift 5 the withUnsafeBytes() method of Data calls the closure with an (untyped) UnsafeRawBufferPointer, and you can load() the value from the raw memory:

let value = data.withUnsafeBytes { $0.load(as: UInt32.self) }

(compare How to use Data.withUnsafeBytes in a well-defined manner? in the Swift forum). Note that this requires that the memory is aligned on a 4-byte boundary. For alternatives see round trip Swift number types to/from Data.

Note also that as of Swift 4.2 you can create a random 32-bit integer simply using the new Random API:

let randomId = UInt32.random(in: .min ... .max)

withUnsafeMutableBytes' is deprecated xcode warning

As @Enricoza points out, the now-deprecated parameter given to the withUnsafeMutableBytes closure is of type UnsafeMutablePointer, and the new one is UnsafeMutableRawBufferPointer. In order to get the UnsafeMutablePointer or UnsafeMutableRawPointer that CommonCrypto can accept, then you need to get the .baseAddress optional property on the *Bytes objects you get from your closures.

Here's a library that uses the new closure parameters: https://github.com/backslash-f/aescryptable/blob/master/Sources/AESCryptable/AESCryptable.swift

You'll note that the main difference is that it unwraps the baseAddresses in a guard clause, throws an error if any fail, then uses those baseAddresses in place of the old parameters to CommonCrypto functions.

withUnsafeBytes' is deprecated warning when passing void* argument to c function in swift 5

You have to change the closure argument to UnsafeRawBufferPointer and then take its baseAdress (which is a UnsafeRawPointer?, the Swift equivalent of void * in C):

data.withUnsafeBytes( { (ptr : UnsafeRawBufferPointer) in
let value = readFITfile(ptr.baseAddress)
// ...
})

The Swift compiler can also infer the closure argument type automatically:

data.withUnsafeBytes( { ptr in
let value = readFITfile(ptr.baseAddress)
// ...
})

For more information about this problem, see withUnsafeBytes Data API confusion in the Swift forum.

Convert Data to UInt32 using extension

Try this:

let data = Data([0x01,0x02,0x03,0x04])
extension Data {
var uint32:UInt32 {
return UInt32(littleEndian: self.withUnsafeBytes { bytes in
bytes.load(as: UInt32.self)
})
}
}
print(String(format: "%08X", data.uint32)) //->04030201

The new withUnsafeBytes passes an UnsafeRawBufferPointer, which has a useful method load(as:).



Related Topics



Leave a reply



Submit