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
|
//===--- 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: []) }
}
public var standardError = CFileStream(fp: stderr)
#if os(Android) || canImport(Musl)
public typealias FILEPointer = OpaquePointer
#else
public typealias FILEPointer = UnsafeMutablePointer<FILE>
#endif
public struct CFileStream: TextOutputStream {
var fp: FILEPointer
public func write(_ string: String) {
fputs(string, fp)
}
public func flush() {
fflush(fp)
}
}
//===----------------------------------------------------------------------===//
// 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 {
_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)
}
}
|