//===--- 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 CxxStdlib /// 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 { 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: BridgedStringRef public init(bridged: BridgedStringRef) { self._bridged = bridged } public var string: String { String(_bridged) } public var description: String { string } public var count: Int { Int(_bridged.size()) } public subscript(index: Int) -> UInt8 { let buffer = UnsafeBufferPointer(start: _bridged.uintData(), count: count) return buffer[index] } public static func ==(lhs: StringRef, rhs: StringRef) -> Bool { let lhsBuffer = UnsafeBufferPointer(start: lhs._bridged.uintData(), count: lhs.count) let rhsBuffer = UnsafeBufferPointer(start: rhs._bridged.uintData(), count: rhs.count) if lhsBuffer.count != rhsBuffer.count { return false } return lhsBuffer.elementsEqual(rhsBuffer, by: ==) } public static func ==(lhs: StringRef, rhs: StaticString) -> Bool { let lhsBuffer = UnsafeBufferPointer(start: lhs._bridged.uintData(), count: lhs.count) 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) } public static func !=(lhs: StringRef, rhs: StringRef) -> Bool { !(lhs == rhs) } public static func ~=(pattern: StaticString, value: StringRef) -> Bool { value == pattern } } //===----------------------------------------------------------------------===// // Bridging Utilities //===----------------------------------------------------------------------===// extension String { public func _withBridgedStringRef(_ c: (BridgedStringRef) -> T) -> T { var str = self return str.withUTF8 { buffer in return c(BridgedStringRef(buffer.baseAddress, buffer.count)) } } public init(_ s: BridgedStringRef) { let buffer = UnsafeBufferPointer(start: s.uintData(), count: Int(s.size())) self.init(decoding: buffer, as: UTF8.self) } public init(taking s: BridgedOwnedString) { let buffer = UnsafeBufferPointer(start: s.uintData(), count: s.size()) self.init(decoding: buffer, as: UTF8.self) s.destroy() } } 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 = unsafeBitCast(object, to: UnsafeMutableRawPointer.self) self = ptr.bindMemory(to: BridgedSwiftObject.self, capacity: 1) } public func getAs(_ objectType: T.Type) -> T { return unsafeBitCast(self, to: T.self) } } extension Optional where Wrapped == UnsafeMutablePointer { public func getAs(_ objectType: T.Type) -> T? { if let pointer = self { return pointer.getAs(objectType) } 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) } }