//===--- Utils.swift - Some bridging utilities ----------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2022 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// @_exported import BasicBridging import std /// The assert function to be used in the compiler. /// /// This overrides the standard Swift assert for two reasons: /// * We also like to check for assert failures in release builds. Although this could be /// achieved with `precondition`, it's easy to forget about it and use `assert` instead. /// * We need to see the error message in crashlogs of release builds. This is even not the /// case for `precondition`. @_transparent public func assert(_ condition: Bool, _ message: @autoclosure () -> String, file: StaticString = #fileID, line: UInt = #line) { if !condition { print("### basic") fatalError(message(), file: file, line: line) } } /// The assert function (without a message) to be used in the compiler. /// /// Unforuntately it's not possible to just add a default argument to `message` in the /// other `assert` function. We need to defined this overload. @_transparent public func assert(_ condition: Bool, file: StaticString = #fileID, line: UInt = #line) { if !condition { fatalError("", file: file, line: line) } } //===----------------------------------------------------------------------===// // Debugging Utilities //===----------------------------------------------------------------------===// /// Let's lldb's `po` command not print any "internal" properties of the conforming type. /// /// This is useful if the `description` already contains all the information of a type instance. public protocol NoReflectionChildren : CustomReflectable { } public extension NoReflectionChildren { var customMirror: Mirror { Mirror(self, children: []) } } //===----------------------------------------------------------------------===// // StringRef //===----------------------------------------------------------------------===// public struct StringRef : CustomStringConvertible, NoReflectionChildren { let _bridged: llvm.StringRef public init(bridged: llvm.StringRef) { self._bridged = bridged } public var string: String { _bridged.string } public var description: String { string } public static func ==(lhs: StringRef, rhs: StaticString) -> Bool { let lhsBuffer = UnsafeBufferPointer( start: lhs._bridged.__bytes_beginUnsafe(), count: Int(lhs._bridged.__bytes_endUnsafe() - lhs._bridged.__bytes_beginUnsafe())) return rhs.withUTF8Buffer { (rhsBuffer: UnsafeBufferPointer) in if lhsBuffer.count != rhsBuffer.count { return false } return lhsBuffer.elementsEqual(rhsBuffer, by: ==) } } public static func !=(lhs: StringRef, rhs: StaticString) -> Bool { !(lhs == rhs) } } //===----------------------------------------------------------------------===// // Bridging Utilities //===----------------------------------------------------------------------===// extension llvm.StringRef { public var string: String { String(_cxxString: self.str()) } } extension String { /// Underscored to avoid name collision with Swift LLVM Bindings. /// To be replaced with a bindings call once bindings are a dependency. public func _withStringRef(_ c: (llvm.StringRef) -> T) -> T { var str = self return str.withUTF8 { buffer in return c(llvm.StringRef(buffer.baseAddress, buffer.count)) } } /// Underscored to avoid name collision with the std overlay. /// To be replaced with an overlay call once the CI uses SDKs built with Swift 5.8. public init(_cxxString s: std.string) { self.init(cString: s.__c_strUnsafe()) withExtendedLifetime(s) {} } } extension Array { public func withBridgedArrayRef(_ c: (BridgedArrayRef) -> T) -> T { return withUnsafeBytes { buf in return c(BridgedArrayRef(data: buf.baseAddress!, numElements: count)) } } } public typealias SwiftObject = UnsafeMutablePointer extension UnsafeMutablePointer where Pointee == BridgedSwiftObject { public init(_ object: T) { let ptr = Unmanaged.passUnretained(object).toOpaque() self = ptr.bindMemory(to: BridgedSwiftObject.self, capacity: 1) } public func getAs(_ objectType: T.Type) -> T { return Unmanaged.fromOpaque(self).takeUnretainedValue() } } extension Optional where Wrapped == UnsafeMutablePointer { public func getAs(_ objectType: T.Type) -> T? { if let pointer = self { return Unmanaged.fromOpaque(pointer).takeUnretainedValue() } return nil } } extension BridgedArrayRef { public func withElements(ofType ty: T.Type, _ c: (UnsafeBufferPointer) -> R) -> R { let start = data?.bindMemory(to: ty, capacity: numElements); let buffer = UnsafeBufferPointer(start: start, count: numElements); return c(buffer) } }