We are getting warnings in the below code. Can anyone suggest what's wrong and what the correct approach would be?
class func getRandomInt64() -> Int64 {
var randomNumber: Int64 = 0
withUnsafeMutablePointer(to: &randomNumber, { (randomNumberPointer) -> Void in
let castedPointer = unsafeBitCast(randomNumberPointer, to: UnsafeMutablePointer<UInt8>.self)
_ = SecRandomCopyBytes(kSecRandomDefault, 8, castedPointer)
})
return abs(randomNumber)
}
Earlier it was fine now it's giving the warning:
'unsafeBitCast' from 'UnsafeMutablePointer' to 'UnsafeMutablePointer' changes pointee type and may lead to undefined behavior; use the 'withMemoryRebound' method on 'UnsafeMutablePointer' to rebind the type of memory
Swift 3 introduced withMemoryRebound, replacing unsafeBitCast and other unsafe casts: https://developer.apple.com/reference/swift/unsafepointer/2430863-withmemoryrebound
The correct way to use it in your case:
class func getRandomInt64() -> Int64 {
var randomNumber: Int64 = 0
withUnsafeMutablePointer(to: &randomNumber, { (randomNumberPointer) -> Void in
_ = randomNumberPointer.withMemoryRebound(to: UInt8.self, capacity: 8, { SecRandomCopyBytes(kSecRandomDefault, 8, $0) })
})
return abs(randomNumber)
}
why not this way?
import Foundation
func randomInt64()->Int64 {
var t = Int64()
arc4random_buf(&t, MemoryLayout<Int64>.size)
return t
}
let i = randomInt64()
or better with generic
import Foundation
func random<T: Integer>()->T {
var t: T = 0
arc4random_buf(&t, MemoryLayout<T>.size)
return t
}
let i:Int = random()
let u: UInt8 = random()
Related
I have a protocol FooProtocol. and a class Bar<Foo:FooProtocol>. Inside a class an Array var mess: [Foo?]? to keep [foo1, foo2, nil, foo3...] or nil
And I try to make extension for this array to count new Foo object. I prefer to have protocols, because Foos could be very different objects delivered from outer world.
protocol FooProtocol {
....
init(from heaven: Int)
}
extension Optional where
Wrapped: Collection,
Wrapped.Element == Optional,
Wrapped.Element.Wrapped: FooProtocol // 'Wrapped' is not a member type of 'Wrapped.Element'
{
var united: Wrapped.Element.Wrapped { // Nope
let i = ...
return Wrapped.Element.Wrapped(from: i) // Nope
}
}
class Bar<Foo:FooProtocol> {
var mess: [Foo?]?
init (with mess: [Foo?]?) {
self.mess = mess
}
var important: Foo {
return mess.united
}
}
Any ideas? I'm blocked.
Edit 1:
After Leo suggestions I changed some parts of my code. But still stucked. This time more code from Playgrounds.
Any object that could be converted into '[Double]'. Could be color (as RGBA), Bezier curve, square, whatever...
public protocol FooProtocol {
var atomized: () -> [Double] {get}
static var count: Int {get}
init(_ array:[Double])
init()
}
public extension Array where Element: FooProtocol {
var average: Element {
var resultAtoms: [Double] = []
let inputAtoms = self.map {$0.atomized()}
for i in 0..<Element.count {
let s = inputAtoms.reduce(into: 0.0, {$0 += $1[i]}) / Double (Element.count)
resultAtoms.append(s)
}
return Element(resultAtoms)
}
}
extension Optional where
Wrapped: Collection,
Wrapped.Element == Optional<FooProtocol>
{
typealias Foo = Wrapped.Element.Wrapped // Doesn't work. How to get class?
var average: Foo { // I cannot use Wrapped.Element, it's Optional
if let thatsList = self {
let withOptionals = Array(thatsList) // OK, its [Optional<FooProtocol>]
let withoutOptionals = thatsList.compactMap({$0}) // OK, its [FooProtocol]
// This is funny, called from class works and makes 'bingo'.
return withoutOptionals.average // Error: Value of protocol type 'FooProtocol' cannot conform to 'FooProtocol'; only struct/enum/class types can conform to protocols
} else {
return Foo() // Hello? init Wrapped? Foo? How to get Foo()?
}
}
}
class Bar<Foo:FooProtocol> {
var mess: [Foo?]?
init (with mess: [Foo?]?) {
self.mess = mess
}
func workOn() {
let z:Foo = mess.average // OK, I can make 'mess.average ?? Foo()' but prefer not do it
}
// Thats OK
func workHard() { // To prove 'Array extension where Element: FooProtocol' works
if let messExist = mess {
let withoutOptionals = messExist.compactMap({$0})
let bingo = withoutOptionals.average //It's OK
}
}
}
class SomeFoo : FooProtocol {
static var count = 3
required init() {
a = 0
b = 0
c = 0
}
required init(_ array: [Double]) {
self.a = Int(array[0])
self.b = Float(array[1])
self.c = array[2]
}
var atomized: () -> [Double] {
return {return [Double(self.a), Double(self.b), self.c]}
}
var a: Int
var b: Float
var c: Double
}
let aFoo = SomeFoo([1, 2, 3])
let bFoo = SomeFoo([7, 9, 1])
let cFoo = SomeFoo([2, 6, 5])
let barData = [nil, aFoo, nil, bFoo, cFoo]
let barWithData = Bar(with: barData)
let barWithoutData = Bar<SomeFoo>(with: nil)
Maybe I should forget about extending array and make some functions inside a class (I'm almost sure I will need those functions somewhere else)
Edit 2
Even if I try to simplify and to make extension for Array I found troubles.
extension Array where
Element == Optional<FooProtocol>
{
func averageNils <Foo: FooProtocol>() -> Foo {
let withOptionals = Array(self) // OK, its [Optional<FooProtocol>]
let withoutOptionals = self.compactMap({$0}) // OK, its [FooProtocol]
return withoutOptionals.average as! Foo // Error: Value of protocol type 'FooProtocol' cannot conform to 'FooProtocol'; only struct/enum/class types can conform to protocols
}
}
From my understanding, it should work as you did, but one never knows what happens in the swift compiler world (and especially it's error messages).
Anyway, you can circumvent digging deeper into Wrapped.Element.Wrapped by specifyig the Wrapped.Element more precisely to be an Optional<FooProtocol>:
protocol FooProtocol {}
class Foo : FooProtocol {}
extension Optional where
Wrapped: Collection, //OK
Wrapped.Element == Optional<FooProtocol> // still good
{
var unfied: Wrapped.Element // Should be 'Foo' if self is '[Foo?]?' {
{
return 1 == 0 ? nil : Foo()
}
}
Ahoy everyone,
I have recently been trying to implement a Node based graph system that passes data between nodes using plugs. Similar to many of the 3D applications like houdini and maya.
I have written a similar system before using Python, and wanted to try this with Swift as my first learning excersise. Boy did I jump into the deep end on this one.
I am stuck now with Swifts Arrays, as I would like to store a list of Generic plugs.
Each plug can have its own value type float, int, color, string, Vector Matrix.
I have read up about Type Erasers and opaque types, but still cant seem to get my values our of a list in a way that I can perform some arithmetic on them.
All and any help that might put me in the direction would be greatly appreciated :D
import Foundation
import MetalKit
protocol genericPlug {
associatedtype T
func GetValue() -> T
}
class Plug<T>:genericPlug{
var _value:T?
var value:T {
get{GetValue()}
set(val){
value = val
}
}
func GetValue() -> T{
return _value!
}
init(_ newValue:T){
_value=newValue
}
}
class Node{
var plugs:[genericPlug] = []
init(){
var p1 = Plug<Int>(0)
var p2 = Plug(vector2(1.2, 3.1))
var p3 = Plug([0.0, 3.1, 0.6, 1])
plugs.append(p1)
plugs.append(p2)
plugs.append(p3)
}
func execute(){
// will access the plugs in the array and perform some sort of calculations on them.
plugs[0].value + 1 // should equal 1
plugs[1].value.x + 0.8 // should have x=2.0 y=3.1
plugs[2].value[1] - 0.1 // should equal 3.0
}
}
Thanks everyone
Use a generic something to extract what you need. Your options are methods and subscripts.
protocol PlugValue {
init()
}
extension Int: PlugValue { }
extension Float: PlugValue { }
extension Double: PlugValue { }
extension SIMD3: PlugValue where Scalar == Int32 { }
struct Plug<Value: PlugValue> {
var value: Value
init(_ value: Value) {
self.value = value
}
}
protocol AnyPlug {
var anyValue: PlugValue { get }
}
extension AnyPlug {
subscript<Value: PlugValue>(type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
func callAsFunction<Value: PlugValue>(_ type: Value.Type = Value.self) -> Value {
anyValue as? Value ?? .init()
}
}
extension Plug: AnyPlug {
var anyValue: PlugValue { value }
}
let plugs: [AnyPlug] = [
Plug(1),
Plug(2.3 as Float),
Plug(4.5),
Plug([6, 7, 8] as SIMD3)
]
plugs[0][Int.self] // 1
plugs[1][Double.self] // 0
plugs[1][] as Float // 2.3
let double: Double = plugs[2]() // 4.5
plugs[3](SIMD3.self).y // 7
With the array of protocols, do you have to down cast them into their Plug when retrieving them every time?
Essentially. This is true of all heterogenous sequences. Here are your options:
extension Array: PlugValue where Element: PlugValue { }
let plug: AnyPlug = Plug([0.1, 1.1, 2.1])
(plug as? Plug<[Double]>)?.value[1]
(plug.anyValue as? [Double])?[1]
extension Plug {
enum Error: Swift.Error {
case typeMismatch
}
}
extension AnyPlug {
func callAsFunction<Value: PlugValue, Return>(_ closure: (Value) -> Return) throws {
guard let value = anyValue as? Value
else { throw Plug<Value>.Error.typeMismatch }
closure(value)
}
}
try plug { (doubles: [Double]) in doubles[1] } // 1.1
try plug { ($0 as [Double])[1] } // 1.1
try plug { $0 as Int } // <Swift.Int>.Error.typeMismatch
I managed to find a solution that worked for my needs.
I am still looking at finding a better way to handle getting the data and their correct type.
import Foundation
import MetalKit
// Creating the PlugType Enum
enum PlugType{
case Integer(Int?)
case Float_(Float?)
case Double_(Double?)
case Vector3(simd_int3)
// default types
static func IntegerType() -> PlugType{ return PlugType.Integer(nil)}
static func FloatType() -> PlugType{ return PlugType.Float_(nil)}
static func DoubleType() -> PlugType{ return PlugType.Double_(nil)}
}
// Implements a way to retrieve the correct value type
extension PlugType{
var IntegerValue: Int{
switch self{
case .Integer(let value):
return value ?? 0
default:
return 0
}
}
var FloatValue: Float{
switch self
{
case .Float_(let value):
return value ?? 0
default:
return 0
}
}
var DoubleValue: Double{
switch self
{
case .Double_(let value):
return value ?? 0
default:
return 0
}
}
}
// Get the string representation of the PlugType
extension PlugType {
var typeName: String{
switch self {
case .Integer: return "Integer"
case .Float_: return "Float"
case .Double_: return "Double"
case .Vector3: return "Vector3"
}
}
var swiftType: Any.Type {
switch self {
case .Integer: return Int.self
case .Float_: return Float.self
case .Double_: return Double.self
case .Vector3: return simd_int3.self
}
}
}
class Plug{
var _value:PlugType?
var type:String? { get{ return _value?.typeName } }
init(_ newValue:PlugType){
_value = newValue
}
func geee<T>(_ input:T) -> T{
switch type {
case "Integer":
return getVal(_value!.IntegerValue) as! T
case "Double":
return getVal(_value!.DoubleValue) as! T
default:
return 0 as! T
}
}
func getVal(_ val:Int) -> Int {
return val
}
func getVal(_ val:Float) -> Float {
return val
}
func getVal(_ val:Double) -> Double {
return val
}
}
var plugs:[Plug] = []
var p1 = Plug(PlugType.Integer(2))
I have a function that allows me to read a number (Integer, Double etc) from a binary file using generic types. For example if I expect a Int64, il will read 8 bytes...
// A simple function that read n bytes from a FileHandle and returns
// the data
public func read(chunkSize: Int) -> Data {
return self.handle!.readData(ofLength: chunkSize)
}
// A function that reads the proper amount of bytes specified
// by the return type which in my case would be an integer
public func readNumber<I>() -> I? {
let data: Data = self.read(chunkSize: MemoryLayout<I>.size)
if data.count == 0 {
return nil
}
return data.withUnsafeBytes { $0.pointee }
}
The readNumber randomly returns nil for no reason. Not from the count check but from the last line.
However it perfectly works when I cast to I like so :
return data.withUnsafeBytes { $0.pointee } as I
Why is that ?
EDIT:
I reproduced this using Playgrounds :
class Test {
public func read(chunkSize: Int) -> Data {
return Data(repeating: 1, count: chunkSize)
}
public func readNumber<T>() -> T? {
let data: Data = read(chunkSize: MemoryLayout<T>.size)
if data.count == 0 {
return nil
}
return data.withUnsafeBytes { $0.pointee }
}
public func example() {
let value2: Double = readNumber()!
print(value2)
}
}
let test = Test()
for i in 0..<1000 {
test.example()
}
Seems I need to correct my comment a little. Even when Swift works consistently as programmed, the result may seem randomly changing, when you have some memory issue like accessing out of bounds.
First prepare a magical extension for UnsafePointer:
extension UnsafePointer {
var printingPointee: Pointee {
print(Pointee.self) //<- Check how Swift inferred `Pointee`
return self.pointee
}
}
And modify your EDIT code a little:
class Test {
public func read(chunkSize: Int) -> Data {
return Data(repeating: 1, count: chunkSize)
}
public func readNumber<T>() -> T? {
let data: Data = read(chunkSize: MemoryLayout<T>.size)
if data.count == 0 {
return nil
}
print(T.self) //<- Check how Swift inferred `T`
return data.withUnsafeBytes { $0.printingPointee }
}
public func example() {
let value2: Double = readNumber()!
print(value2)
}
}
let test = Test()
for _ in 0..<1000 {
test.example()
}
Output:
Double
Optional<Double>
7.748604185489348e-304
Double
Optional<Double>
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
How many pairs of Double and Optional<Double> shown would be seemingly random, but the cause of this behavior is quite clear.
In this line return data.withUnsafeBytes { $0.printingPointee }, Swift infers the type of $0 as UnsafePointer<Optional<Double>>.
In the current implementation of Swift, Optional<Double> occupies 9 bytes in memory:
print(MemoryLayout<Optional<Double>>.size) //-> 9
So, $0.pointee accesses 9 bytes starting from the pointer, although the pointer is pointing to the region of 8-byte:
|+0|+1|+2|+3|+4|+5|+6|+7|+8|
+--+--+--+--+--+--+--+--+
01 01 01 01 01 01 01 01 ??
<-taken from the Data->
As you know, the extra 9th (+8) byte cannot be predictable and may seemingly be random, which is an indicator of nil in Optional<Double>.
Exactly the same inference is working in your code. In your readNumber<T>(), the return type is clearly declared as T?, so, in the line return data.withUnsafeBytes { $0.pointee }, it is very natural that Swift infers the type of $0.pointee as Double? aka Optional<Double>.
You know you can control this type inference with adding as T.
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.)
edit/update: Xcode 12.5 • Swift 5.4
extension ContiguousBytes {
func object<T>() -> T { withUnsafeBytes { $0.load(as: T.self) } }
}
extension Data {
func subdata<R: RangeExpression>(in range: R) -> Self where R.Bound == Index {
subdata(in: range.relative(to: self) )
}
func object<T>(at offset: Int) -> T { subdata(in: offset...).object() }
}
extension Numeric {
var data: Data {
var source = self
return Data(bytes: &source, count: MemoryLayout<Self>.size)
}
}
struct AwesomeStructure {
let index: Int32
let id: UInt16
let stuff: UInt8
}
extension AwesomeStructure {
init(data: Data) {
index = data.object()
id = data.object(at: 4)
stuff = data.object(at: 6)
}
var data: Data { index.data + id.data + stuff.data }
}
let awesomeStructure = AwesomeStructure(index: 1, id: 2, stuff: 3)
let data = awesomeStructure.data
print(data) // 7 bytes
let structFromData = AwesomeStructure(data: data)
print(structFromData) // "AwesomeStructure(index: 1, id: 2, stuff: 3)\n"
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.
Here's a decent first approximation. The trick is to use Swift.withUnsafeBytes(_:) to get a UnsafeRawBufferPointer, which can then be easily converted to Data using Data.init<SourceType>(buffer: UnsafeMutableBufferPointer<SourceType>).
This causes a copy of the memory, so you don't have to worry about any sort of dangling pointer issues.
import Foundation
struct AwesomeStructure {
let index: Int32 = 0x56
let id: UInt16 = 0x34
let stuff: UInt8 = 0x12
}
func toData<T>(_ input: inout T) -> Data {
var data = withUnsafeBytes(of: &input, Data.init)
let alignment = MemoryLayout<T>.alignment
let remainder = data.count % alignment
if remainder == 0 {
return data
}
else {
let paddingByteCount = alignment - remainder
return data + Data(count: paddingByteCount)
}
}
extension Data {
var prettyString: String {
return self.enumerated()
.lazy
.map { byteNumber, byte in String(format:"/* %02i */ 0x%02X", byteNumber, byte) }
.joined(separator: "\n")
}
}
var x = AwesomeStructure()
let d = toData(&x)
print(d.prettyString)
I have the following Problem. I want to convert my old function (worked until Swift 3 beta 5):
func binarytotype <T> (_ value: [UInt8], _: T.Type) -> T
{
return value.withUnsafeBufferPointer
{
return UnsafePointer<T>($0.baseAddress!).pointee
}
}
To Swift 3 beta 6 Syntax. This function converts an array of UInt8 to another type, for example:
let b: [UInt8] = [1,2,3,4,5,6,7,8]
var number: Double = binarytotype(b, Double.self)
But for now this does not work any more in beta 6 and I have to use withMemoryRebound but I really do not know, how to make it run. Can anybody help me?
The reverse function of this was:
func typetobinary <T> (_ value: T) -> [UInt8]
{
var v: T = value
return withUnsafePointer(to: &v)
{
Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>($0), count: MemoryLayout<T>.size))
}
}
This does not work any more, too. Same problem. Both are needed for some of my projects. This reverse function was called as:
var binary: [UInt8] = typetobinary(number)
Pointer conversions are much more "verbose" now since Xcode 8 beta 6.
Here is a possible solution:
func binarytotype <T> (_ value: [UInt8], _: T.Type) -> T {
return value.withUnsafeBufferPointer {
UnsafeRawPointer($0.baseAddress!).load(as: T.self)
}
}
func typetobinary<T>(_ value: T) -> [UInt8] {
var data = [UInt8](repeating: 0, count: MemoryLayout<T>.size)
data.withUnsafeMutableBufferPointer {
UnsafeMutableRawPointer($0.baseAddress!).storeBytes(of: value, as: T.self)
}
return data
}
Example:
let d = typetobinary(UInt16(1000))
print(d) // [232, 3]
let i = binarytotype(d, UInt16.self)
print(i) // 1000
See SE-0107 UnsafeRawPointer API for
detailed information about the new raw pointer API.