1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
//===--- 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
/// 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, function: StaticString = #function) {
precondition(condition, message(), file: file, line: line, function: function)
}
/// 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.
/// TODO: For some reason the compiler is not happy when adding a `function` argument.
@_transparent
public func assert(_ condition: Bool, file: StaticString = #fileID, line: UInt = #line) {
precondition(condition, "", file: file, line: line, function: "")
}
/// The assert function to be used in the compiler.
///
/// This overrides the standard Swift precondition and forwards an assertion failure
/// to the assertion-handling in the C++ code base.
@_transparent
public func precondition(_ condition: Bool, _ message: @autoclosure () -> String,
file: StaticString = #fileID, line: UInt = #line, function: StaticString = #function) {
if !_fastPath(condition) {
let msg = message()
msg.withCString { msgStr in
file.withUTF8Buffer { fileBytes in
function.withUTF8Buffer { functionBytes in
assertFail(msgStr, fileBytes.baseAddress!, line, functionBytes.baseAddress!)
}
}
}
}
}
//===----------------------------------------------------------------------===//
// Debugging Utilities
//===----------------------------------------------------------------------===//
public func debugLog(prefix: Bool = true, _ message: @autoclosure () -> String) {
let formatted = (prefix ? "### " : "") + message()
formatted._withBridgedStringRef { ref in
Bridged_dbgs().write(ref)
}
Bridged_dbgs().newLine()
}
/// 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 {
public 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 {
_bridged.count
}
public subscript(index: Int) -> UInt8 {
let buffer = UnsafeBufferPointer<UInt8>(start: _bridged.data, count: count)
return buffer[index]
}
public static func ==(lhs: StringRef, rhs: StringRef) -> Bool {
let lhsBuffer = UnsafeBufferPointer<UInt8>(start: lhs._bridged.data, count: lhs.count)
let rhsBuffer = UnsafeBufferPointer<UInt8>(start: rhs._bridged.data, 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<UInt8>(start: lhs._bridged.data, count: lhs.count)
return rhs.withUTF8Buffer { (rhsBuffer: UnsafeBufferPointer<UInt8>) 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<T>(_ c: (BridgedStringRef) -> T) -> T {
var str = self
return str.withUTF8 { buffer in
return c(BridgedStringRef(data: buffer.baseAddress, count: buffer.count))
}
}
public init(_ s: BridgedStringRef) {
let buffer = UnsafeBufferPointer<UInt8>(start: s.data, count: s.count)
self.init(decoding: buffer, as: UTF8.self)
}
public init(taking s: BridgedOwnedString) {
let buffer = UnsafeBufferPointer<UInt8>(start: s.data, count: s.count)
self.init(decoding: buffer, as: UTF8.self)
s.destroy()
}
}
extension Array {
public func withBridgedArrayRef<T>(_ c: (BridgedArrayRef) -> T) -> T {
return withUnsafeBytes { buf in
return c(BridgedArrayRef(data: buf.baseAddress!, count: count))
}
}
}
public typealias SwiftObject = UnsafeMutablePointer<BridgedSwiftObject>
extension UnsafeMutablePointer where Pointee == BridgedSwiftObject {
public init<T: AnyObject>(_ object: T) {
let ptr = unsafeBitCast(object, to: UnsafeMutableRawPointer.self)
self = ptr.bindMemory(to: BridgedSwiftObject.self, capacity: 1)
}
public func getAs<T: AnyObject>(_ objectType: T.Type) -> T {
return unsafeBitCast(self, to: T.self)
}
}
extension Optional where Wrapped == UnsafeMutablePointer<BridgedSwiftObject> {
public func getAs<T: AnyObject>(_ objectType: T.Type) -> T? {
if let pointer = self {
return pointer.getAs(objectType)
}
return nil
}
}
extension BridgedArrayRef {
public func withElements<T, R>(ofType ty: T.Type, _ c: (UnsafeBufferPointer<T>) -> R) -> R {
let start = data?.bindMemory(to: ty, capacity: count)
let buffer = UnsafeBufferPointer(start: start, count: count)
return c(buffer)
}
}
//===----------------------------------------------------------------------===//
// Sequence Utilities
//===----------------------------------------------------------------------===//
/// RandomAccessCollection which bridges to some C++ array.
///
/// It fixes the default reflection for bridged random access collections, which usually have a
/// `bridged` stored property.
/// Conforming to this protocol displays the "real" children not just `bridged`.
public protocol BridgedRandomAccessCollection : RandomAccessCollection, CustomReflectable {
}
extension BridgedRandomAccessCollection {
public var customMirror: Mirror {
Mirror(self, children: self.map { (label: nil, value: $0 as Any) })
}
}
|