├── .github
└── workflows
│ └── swift.yml
├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── LICENSE
├── Package.swift
├── README.md
├── Sources
├── AssociatedTypeRequirementsVisitor
│ ├── AssociatedTypeRequirementsTypeVisitor.swift
│ ├── AssociatedTypeRequirementsVisitor.swift
│ ├── _test.swift
│ ├── testTypes.swift
│ ├── visitors.swift
│ └── visitors.swift.gyb
├── CContext
│ ├── CContext.c
│ └── include
│ │ └── CContext.h
├── Casting
│ ├── CastedProtocolValue.swift
│ └── withCasted.swift
├── ProtocolConformance
│ ├── ProtocolConformanceRecord.swift
│ ├── fakeConformance.swift
│ ├── helpers.swift
│ └── helpers.swift.gyb
├── ProtocolType
│ ├── ModuleName.swift
│ ├── ModuleName.swift.gyb
│ ├── ProtocolName.swift
│ ├── ProtocolName.swift.gyb
│ ├── ProtocolType.swift
│ └── ProtocolType.swift.gyb
└── ValuePointers
│ └── withUnsafeValuePointer.swift
├── Tests
├── AssociatedTypeRequirementsKitTests
│ ├── ProtocolTypeTests.swift
│ ├── ValuePointersTests.swift
│ ├── VisitorTests.swift
│ └── XCTestManifests.swift
└── LinuxMain.swift
├── commonProtocols.json
├── swift-error-message.png
└── useGYB
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | name: Build and Test
2 |
3 | on:
4 | push:
5 | branches:
6 | - develop
7 | - release
8 | pull_request:
9 | branches:
10 | - develop
11 | - release
12 |
13 | jobs:
14 | macos:
15 | runs-on: macos-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 | - uses: maxim-lobanov/setup-xcode@v1.1
19 | with:
20 | xcode-version: latest
21 | - name: Check Xcode version
22 | run: xcodebuild -version
23 | - name: Check Swift version
24 | run: swift --version
25 | - name: Build
26 | run: swift build
27 | - name: Test
28 | run: swift test
29 | linux:
30 | container:
31 | image: swift:${{ matrix.linux }}
32 | runs-on: ubuntu-latest
33 | strategy:
34 | matrix:
35 | linux: [bionic, xenial, focal]
36 | steps:
37 | - uses: actions/checkout@v2
38 | - name: Install libsqlite3
39 | run: apt-get update && apt-get install -y --no-install-recommends libsqlite3-dev
40 | - name: Check Swift version
41 | run: swift --version
42 | - name: Build
43 | run: swift build
44 | - name: Test
45 | run: swift test
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Mathias Quintero
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "AssociatedTypeRequirementsKit",
8 | products: [
9 | .library(name: "AssociatedTypeRequirementsKit",
10 | targets: ["AssociatedTypeRequirementsVisitor", "Casting", "ValuePointers", "ProtocolType"]),
11 | ],
12 | dependencies: [],
13 | targets: [
14 | .target(
15 | name: "AssociatedTypeRequirementsVisitor",
16 | dependencies: ["Casting", "ValuePointers", "CContext"]),
17 |
18 | .target(
19 | name: "Casting",
20 | dependencies: ["ValuePointers", "ProtocolType"]),
21 |
22 | .target(
23 | name: "ValuePointers",
24 | dependencies: ["ProtocolConformance"]),
25 |
26 | .target(
27 | name: "ProtocolType",
28 | dependencies: []),
29 |
30 | .target(
31 | name: "ProtocolConformance",
32 | dependencies: ["ProtocolType"]),
33 |
34 | .target(
35 | name: "CContext",
36 | dependencies: []),
37 |
38 | .testTarget(
39 | name: "AssociatedTypeRequirementsKitTests",
40 | dependencies: ["AssociatedTypeRequirementsVisitor", "Casting", "ValuePointers", "ProtocolType"]),
41 | ]
42 | )
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AssociatedTypeRequirementsKit
2 |
3 | Is Swift bothering you with those pesky error messages? Something something about associated type requirements. Like when you want to cast something to a protocol, but then:
4 |
5 | 
6 |
7 | Well not to worry. Introducing AssociatedTypeRequirementsKit 🤗
8 | A collection of µFrameworks to help you get around those annoying scenarios!
9 |
10 | Our example from before is dealt like so:
11 |
12 | ```swift
13 | import AssociatedTypeRequirementsVisitor
14 |
15 | private let hasher = AnyHasher()
16 |
17 | func hashValue(value: Any) -> Int {
18 | // There's a function `AnyHasher.callAsFunction(_:Any) -> Int?`
19 | return hasher(value) ?? 0
20 | }
21 |
22 | struct AnyHasher: HashableVisitor {
23 | // This function will called by `callAsFunction(_:Any)` if the input conforms to hashable
24 | func callAsFunction(_ value: T) -> Int {
25 | return value.hashValue
26 | }
27 | }
28 | ```
29 |
30 | ## Installation
31 | ### Swift Package Manager
32 |
33 | You can install AssociatedTypeRequirementsKit via [Swift Package Manager](https://swift.org/package-manager/) by adding the following line to your `Package.swift`:
34 |
35 | ```swift
36 | import PackageDescription
37 |
38 | let package = Package(
39 | [...]
40 | dependencies: [
41 | .package(url: "https://github.com/nerdsupremacist/AssociatedTypeRequirementsKit.git", from: "0.1.0")
42 | ]
43 | )
44 | ```
45 |
46 | ## Usage
47 |
48 | ### AssociatedTypeRequirementsVisitor
49 |
50 | If you want to be able to call a function on a protocol with associated types, then you'll have to provide a generic function. Since closures cannot be generic, we have to use a protocol to encode this.
51 |
52 | For example if you want to be able to turn any SwiftUI view into an AnyView, but you don't know the type at compile time, you can use `ViewVisitor`:
53 |
54 | ```swift
55 | import AssociatedTypeRequirementsVisitor
56 | import SwiftUI
57 |
58 | private let converter = AnyViewConverter()
59 |
60 | extension AnyView {
61 | init?(_ value: Any) {
62 | guard let view = converter(value) else { return nil }
63 | self = view
64 | }
65 | }
66 |
67 | private struct AnyViewConverter : ViewVisitor {
68 | // Provide a function that can be called with all the necessary type information
69 | func callAsFunction(_ value: T) -> AnyView {
70 | return AnyView(value)
71 | }
72 | }
73 | ```
74 |
75 | But why would you need to do this? Well, for example if you want to get all the subviews of a tuple view?
76 |
77 | ```swift
78 | extension TupleView {
79 |
80 | func subviews() -> [AnyView] {
81 | let mirror = Mirror(reflecting: self)
82 | let tuple = mirror.children.first!.value
83 | let tupleMirror = Mirror(reflecting: tuple)
84 | return tupleMirror.children.map { AnyView($0.value)! }
85 | }
86 |
87 | }
88 | ```
89 |
90 | `ViewVisitor` is available out of the box because we are already shipping visitor protocols for the most important problematic protocols in Swift right now, and are extending the list as we go.
91 | If you have to handle your own protocol you can do it as in the following example:
92 |
93 | ```swift
94 | protocol MyProtocolVisitor: AssociatedTypeRequirementsVisitor {
95 | associatedtype Visitor = MyProtocolVisitor
96 | associatedtype Input = MyProtocol
97 | associatedtype Output
98 |
99 | func callAsFunction(_ value: T) -> Output
100 | }
101 | ```
102 |
103 | ### Casting
104 |
105 | If you don't want to use the `AssociatedTypeRequirementsVisitor` API, you can also ask use the low level `withCasted` API and ask for the protocol conformance yourself.
106 |
107 | ```swift
108 | import Casting
109 |
110 | func test(value: Any) -> AnyHashable? {
111 | return withCasted(value, as: .hashable) { casted in
112 | // casted is CastedProtocolValue
113 | ...
114 | }
115 | }
116 | ```
117 |
118 | But what is this `CastedProtocolValue`? Well it's a little struct that has the same layout that a function `func anyHashable(hashable: T)` would expect. So that function could be casted:
119 |
120 | ```swift
121 | import Casting
122 |
123 | func test(value: Any) -> AnyHashable? {
124 | return withCasted(value, as: .hashable) { casted in
125 | // A pointer to the function is in `functionPointer`
126 | let function = unsafeBitCast(functionPointer, (@convention(thin) (CastedProtocolValue) -> AnyHashable).self)
127 | return function(casted)
128 | }
129 | }
130 | ```
131 |
132 | ### ValuePointers
133 |
134 | When you use the `withUnsafePointer` API from the Swift Standard Library, but with `Any` you'll notice that the pointer or bytes you get are not quite correct.
135 | That's becasue they're pointing to the existential container `Any`, which is always 32 Bytes.
136 |
137 | That's why we ship `withUnsafeValuePointer` which will always point to the actual value, instead of the container:
138 |
139 | ```swift
140 | import ValuePointers
141 |
142 | struct MyStruct {
143 | let first: String
144 | let second: String
145 | }
146 |
147 | let value = MyStruct(first: "A", second: "B") as Any
148 | let secondString = withUnsafeValuePointer(to: value) { $0.assumingMemoryBound(to: String.self).advanced(by: 1).pointee }
149 |
150 | // "B"
151 | print(secondString)
152 | ```
153 |
154 | ### ProtocolType
155 |
156 | Whenever you want to access the meta-type of a protocol with associated types, you'll run into this exact same problem.
157 | You can use `ProtocolType` to access it via the name of the protocol:
158 |
159 | ```swift
160 | import ProtocolType
161 |
162 | let protocolType = ProtocolType(moduleName: "SwiftUI", protocolName: "View")
163 | print(protocolType?.type) // SwiftUI.View.self
164 | ```
165 |
166 | And ProtocolType provides a set of constants already shipped. The list of constants can be changed in the `commonProtocols.json` file and can be extended further:
167 |
168 | ```swift
169 | import ProtocolType
170 |
171 | func hash(protocol protocolType: ProtocolType) -> some Hashable {
172 | return unsafeBitCast(type, as: Int.self)
173 | }
174 |
175 | let hashed = hash(protocol: .collection)
176 | ```
177 |
178 | ## Contributions
179 | Contributions are welcome and encouraged!
180 |
181 | ## License
182 | AssociatedTypeRequirementsKit is available under the MIT license. See the LICENSE file for more info.
183 |
--------------------------------------------------------------------------------
/Sources/AssociatedTypeRequirementsVisitor/AssociatedTypeRequirementsTypeVisitor.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import ProtocolConformance
4 | import ProtocolType
5 | import Casting
6 | import CContext
7 |
8 | public protocol AssociatedTypeRequirementsTypeVisitor {
9 | associatedtype Visitor
10 | associatedtype Input
11 | associatedtype Output
12 |
13 | func _test()
14 | }
15 |
16 | extension AssociatedTypeRequirementsTypeVisitor {
17 |
18 | public func callAsFunction(_ type: Any.Type) -> Output? {
19 | if _isTesting {
20 | _test()
21 | _testAssocaitedTypeRequirementVisitors(false)
22 | }
23 |
24 | guard let visitorWitnessTable = ProtocolConformanceRecord(implementationType: Self.self, protocolType: Visitor.self) else { return nil }
25 | guard let conformanceRecord = ProtocolConformanceRecord(implementationType: type, protocolType: Input.self) else { return nil }
26 |
27 | let functionPointer = visitorWitnessTable.witnessTable!.assumingMemoryBound(to: UnsafeRawPointer.self).advanced(by: 2).pointee
28 | let function = unsafeBitCast(functionPointer, to: (@convention(thin) (UnsafeRawPointer, ProtocolConformanceRecord, UnsafeRawPointer) -> Output).self)
29 | return withUnsafePointer(to: self) { selfPointer in
30 | let typePointer = unsafeBitCast(type, to: UnsafeRawPointer.self)
31 | set_self_pointer(UnsafeMutableRawPointer(mutating: UnsafeRawPointer(selfPointer)))
32 | return function(typePointer, conformanceRecord, conformanceRecord.witnessTable!)
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/AssociatedTypeRequirementsVisitor/AssociatedTypeRequirementsVisitor.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import ProtocolConformance
4 | import ProtocolType
5 | import Casting
6 | import CContext
7 |
8 | public protocol AssociatedTypeRequirementsVisitor {
9 | associatedtype Visitor
10 | associatedtype Input
11 | associatedtype Output
12 |
13 | func _test()
14 | }
15 |
16 | extension AssociatedTypeRequirementsVisitor {
17 |
18 | public func callAsFunction(_ value: Any) -> Output? {
19 | if _isTesting {
20 | _test()
21 | _testAssocaitedTypeRequirementVisitors(false)
22 | }
23 |
24 | guard let visitorWitnessTable = ProtocolConformanceRecord(implementationType: Self.self, protocolType: Visitor.self) else { return nil }
25 | return withCasted(value, as: Input.self) { casted in
26 | let functionPointer = visitorWitnessTable.witnessTable!.assumingMemoryBound(to: UnsafeRawPointer.self).advanced(by: 2).pointee
27 | let function = unsafeBitCast(functionPointer, to: (@convention(thin) (CastedProtocolValue) -> Output).self)
28 | return withUnsafePointer(to: self) { selfPointer in
29 | set_self_pointer(UnsafeMutableRawPointer(mutating: UnsafeRawPointer(selfPointer)))
30 | return function(casted)
31 | }
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/AssociatedTypeRequirementsVisitor/_test.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | var _isTesting = false
5 |
6 | public func _testAssocaitedTypeRequirementVisitors(_ newValue: Bool) {
7 | _isTesting = newValue
8 | }
9 |
--------------------------------------------------------------------------------
/Sources/AssociatedTypeRequirementsVisitor/testTypes.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | enum TestRawRepresentable: String {
5 | case test
6 | }
7 |
8 | struct TestIdentifiable: Identifiable {
9 | let id: String
10 | }
11 |
--------------------------------------------------------------------------------
/Sources/AssociatedTypeRequirementsVisitor/visitors.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import ProtocolType
4 |
5 |
6 | // Swift
7 | #if canImport(Swift)
8 | import Swift
9 |
10 | public protocol BinaryFloatingPointVisitor: AssociatedTypeRequirementsVisitor {
11 | associatedtype Visitor = BinaryFloatingPointVisitor
12 | associatedtype Input = BinaryFloatingPoint
13 | associatedtype Output
14 |
15 | func callAsFunction(_ value: T) -> Output
16 | }
17 |
18 | extension BinaryFloatingPointVisitor {
19 |
20 | @inline(never)
21 | @_optimize(none)
22 | public func _test() {
23 | _ = self(42.0) as Output
24 | }
25 |
26 | }
27 |
28 | public protocol BinaryFloatingPointTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
29 | associatedtype Visitor = BinaryFloatingPointTypeVisitor
30 | associatedtype Input = BinaryFloatingPoint
31 | associatedtype Output
32 |
33 | func callAsFunction(_ type: T.Type) -> Output
34 | }
35 |
36 | extension BinaryFloatingPointTypeVisitor {
37 |
38 | @inline(never)
39 | @_optimize(none)
40 | public func _test() {
41 | _ = self(Double.self) as Output
42 | }
43 |
44 | }
45 |
46 | public protocol EncodableVisitor: AssociatedTypeRequirementsVisitor {
47 | associatedtype Visitor = EncodableVisitor
48 | associatedtype Input = Encodable
49 | associatedtype Output
50 |
51 | func callAsFunction(_ value: T) -> Output
52 | }
53 |
54 | extension EncodableVisitor {
55 |
56 | @inline(never)
57 | @_optimize(none)
58 | public func _test() {
59 | _ = self(42) as Output
60 | }
61 |
62 | }
63 |
64 | public protocol EncodableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
65 | associatedtype Visitor = EncodableTypeVisitor
66 | associatedtype Input = Encodable
67 | associatedtype Output
68 |
69 | func callAsFunction(_ type: T.Type) -> Output
70 | }
71 |
72 | extension EncodableTypeVisitor {
73 |
74 | @inline(never)
75 | @_optimize(none)
76 | public func _test() {
77 | _ = self(Int.self) as Output
78 | }
79 |
80 | }
81 |
82 | public protocol DecodableVisitor: AssociatedTypeRequirementsVisitor {
83 | associatedtype Visitor = DecodableVisitor
84 | associatedtype Input = Decodable
85 | associatedtype Output
86 |
87 | func callAsFunction(_ value: T) -> Output
88 | }
89 |
90 | extension DecodableVisitor {
91 |
92 | @inline(never)
93 | @_optimize(none)
94 | public func _test() {
95 | _ = self(42) as Output
96 | }
97 |
98 | }
99 |
100 | public protocol DecodableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
101 | associatedtype Visitor = DecodableTypeVisitor
102 | associatedtype Input = Decodable
103 | associatedtype Output
104 |
105 | func callAsFunction(_ type: T.Type) -> Output
106 | }
107 |
108 | extension DecodableTypeVisitor {
109 |
110 | @inline(never)
111 | @_optimize(none)
112 | public func _test() {
113 | _ = self(Int.self) as Output
114 | }
115 |
116 | }
117 |
118 | public protocol RandomNumberGeneratorVisitor: AssociatedTypeRequirementsVisitor {
119 | associatedtype Visitor = RandomNumberGeneratorVisitor
120 | associatedtype Input = RandomNumberGenerator
121 | associatedtype Output
122 |
123 | func callAsFunction(_ value: T) -> Output
124 | }
125 |
126 | extension RandomNumberGeneratorVisitor {
127 |
128 | @inline(never)
129 | @_optimize(none)
130 | public func _test() {
131 | _ = self(SystemRandomNumberGenerator()) as Output
132 | }
133 |
134 | }
135 |
136 | public protocol RandomNumberGeneratorTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
137 | associatedtype Visitor = RandomNumberGeneratorTypeVisitor
138 | associatedtype Input = RandomNumberGenerator
139 | associatedtype Output
140 |
141 | func callAsFunction(_ type: T.Type) -> Output
142 | }
143 |
144 | extension RandomNumberGeneratorTypeVisitor {
145 |
146 | @inline(never)
147 | @_optimize(none)
148 | public func _test() {
149 | _ = self(SystemRandomNumberGenerator.self) as Output
150 | }
151 |
152 | }
153 |
154 | public protocol HashableVisitor: AssociatedTypeRequirementsVisitor {
155 | associatedtype Visitor = HashableVisitor
156 | associatedtype Input = Hashable
157 | associatedtype Output
158 |
159 | func callAsFunction(_ value: T) -> Output
160 | }
161 |
162 | extension HashableVisitor {
163 |
164 | @inline(never)
165 | @_optimize(none)
166 | public func _test() {
167 | _ = self(42) as Output
168 | }
169 |
170 | }
171 |
172 | public protocol HashableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
173 | associatedtype Visitor = HashableTypeVisitor
174 | associatedtype Input = Hashable
175 | associatedtype Output
176 |
177 | func callAsFunction(_ type: T.Type) -> Output
178 | }
179 |
180 | extension HashableTypeVisitor {
181 |
182 | @inline(never)
183 | @_optimize(none)
184 | public func _test() {
185 | _ = self(Int.self) as Output
186 | }
187 |
188 | }
189 |
190 | public protocol NumericVisitor: AssociatedTypeRequirementsVisitor {
191 | associatedtype Visitor = NumericVisitor
192 | associatedtype Input = Numeric
193 | associatedtype Output
194 |
195 | func callAsFunction(_ value: T) -> Output
196 | }
197 |
198 | extension NumericVisitor {
199 |
200 | @inline(never)
201 | @_optimize(none)
202 | public func _test() {
203 | _ = self(42) as Output
204 | }
205 |
206 | }
207 |
208 | public protocol NumericTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
209 | associatedtype Visitor = NumericTypeVisitor
210 | associatedtype Input = Numeric
211 | associatedtype Output
212 |
213 | func callAsFunction(_ type: T.Type) -> Output
214 | }
215 |
216 | extension NumericTypeVisitor {
217 |
218 | @inline(never)
219 | @_optimize(none)
220 | public func _test() {
221 | _ = self(Int.self) as Output
222 | }
223 |
224 | }
225 |
226 | public protocol BidirectionalCollectionVisitor: AssociatedTypeRequirementsVisitor {
227 | associatedtype Visitor = BidirectionalCollectionVisitor
228 | associatedtype Input = BidirectionalCollection
229 | associatedtype Output
230 |
231 | func callAsFunction(_ value: T) -> Output
232 | }
233 |
234 | extension BidirectionalCollectionVisitor {
235 |
236 | @inline(never)
237 | @_optimize(none)
238 | public func _test() {
239 | _ = self([42]) as Output
240 | }
241 |
242 | }
243 |
244 | public protocol BidirectionalCollectionTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
245 | associatedtype Visitor = BidirectionalCollectionTypeVisitor
246 | associatedtype Input = BidirectionalCollection
247 | associatedtype Output
248 |
249 | func callAsFunction(_ type: T.Type) -> Output
250 | }
251 |
252 | extension BidirectionalCollectionTypeVisitor {
253 |
254 | @inline(never)
255 | @_optimize(none)
256 | public func _test() {
257 | _ = self(Array.self) as Output
258 | }
259 |
260 | }
261 |
262 | public protocol RandomAccessCollectionVisitor: AssociatedTypeRequirementsVisitor {
263 | associatedtype Visitor = RandomAccessCollectionVisitor
264 | associatedtype Input = RandomAccessCollection
265 | associatedtype Output
266 |
267 | func callAsFunction(_ value: T) -> Output
268 | }
269 |
270 | extension RandomAccessCollectionVisitor {
271 |
272 | @inline(never)
273 | @_optimize(none)
274 | public func _test() {
275 | _ = self([42]) as Output
276 | }
277 |
278 | }
279 |
280 | public protocol RandomAccessCollectionTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
281 | associatedtype Visitor = RandomAccessCollectionTypeVisitor
282 | associatedtype Input = RandomAccessCollection
283 | associatedtype Output
284 |
285 | func callAsFunction(_ type: T.Type) -> Output
286 | }
287 |
288 | extension RandomAccessCollectionTypeVisitor {
289 |
290 | @inline(never)
291 | @_optimize(none)
292 | public func _test() {
293 | _ = self(Array.self) as Output
294 | }
295 |
296 | }
297 |
298 | public protocol ComparableVisitor: AssociatedTypeRequirementsVisitor {
299 | associatedtype Visitor = ComparableVisitor
300 | associatedtype Input = Comparable
301 | associatedtype Output
302 |
303 | func callAsFunction(_ value: T) -> Output
304 | }
305 |
306 | extension ComparableVisitor {
307 |
308 | @inline(never)
309 | @_optimize(none)
310 | public func _test() {
311 | _ = self(42) as Output
312 | }
313 |
314 | }
315 |
316 | public protocol ComparableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
317 | associatedtype Visitor = ComparableTypeVisitor
318 | associatedtype Input = Comparable
319 | associatedtype Output
320 |
321 | func callAsFunction(_ type: T.Type) -> Output
322 | }
323 |
324 | extension ComparableTypeVisitor {
325 |
326 | @inline(never)
327 | @_optimize(none)
328 | public func _test() {
329 | _ = self(Int.self) as Output
330 | }
331 |
332 | }
333 |
334 | public protocol CollectionVisitor: AssociatedTypeRequirementsVisitor {
335 | associatedtype Visitor = CollectionVisitor
336 | associatedtype Input = Collection
337 | associatedtype Output
338 |
339 | func callAsFunction(_ value: T) -> Output
340 | }
341 |
342 | extension CollectionVisitor {
343 |
344 | @inline(never)
345 | @_optimize(none)
346 | public func _test() {
347 | _ = self([42]) as Output
348 | }
349 |
350 | }
351 |
352 | public protocol CollectionTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
353 | associatedtype Visitor = CollectionTypeVisitor
354 | associatedtype Input = Collection
355 | associatedtype Output
356 |
357 | func callAsFunction(_ type: T.Type) -> Output
358 | }
359 |
360 | extension CollectionTypeVisitor {
361 |
362 | @inline(never)
363 | @_optimize(none)
364 | public func _test() {
365 | _ = self(Array.self) as Output
366 | }
367 |
368 | }
369 |
370 | public protocol MutableCollectionVisitor: AssociatedTypeRequirementsVisitor {
371 | associatedtype Visitor = MutableCollectionVisitor
372 | associatedtype Input = MutableCollection
373 | associatedtype Output
374 |
375 | func callAsFunction(_ value: T) -> Output
376 | }
377 |
378 | extension MutableCollectionVisitor {
379 |
380 | @inline(never)
381 | @_optimize(none)
382 | public func _test() {
383 | _ = self([42]) as Output
384 | }
385 |
386 | }
387 |
388 | public protocol MutableCollectionTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
389 | associatedtype Visitor = MutableCollectionTypeVisitor
390 | associatedtype Input = MutableCollection
391 | associatedtype Output
392 |
393 | func callAsFunction(_ type: T.Type) -> Output
394 | }
395 |
396 | extension MutableCollectionTypeVisitor {
397 |
398 | @inline(never)
399 | @_optimize(none)
400 | public func _test() {
401 | _ = self(Array.self) as Output
402 | }
403 |
404 | }
405 |
406 | public protocol RangeReplaceableCollectionVisitor: AssociatedTypeRequirementsVisitor {
407 | associatedtype Visitor = RangeReplaceableCollectionVisitor
408 | associatedtype Input = RangeReplaceableCollection
409 | associatedtype Output
410 |
411 | func callAsFunction(_ value: T) -> Output
412 | }
413 |
414 | extension RangeReplaceableCollectionVisitor {
415 |
416 | @inline(never)
417 | @_optimize(none)
418 | public func _test() {
419 | _ = self([42]) as Output
420 | }
421 |
422 | }
423 |
424 | public protocol RangeReplaceableCollectionTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
425 | associatedtype Visitor = RangeReplaceableCollectionTypeVisitor
426 | associatedtype Input = RangeReplaceableCollection
427 | associatedtype Output
428 |
429 | func callAsFunction(_ type: T.Type) -> Output
430 | }
431 |
432 | extension RangeReplaceableCollectionTypeVisitor {
433 |
434 | @inline(never)
435 | @_optimize(none)
436 | public func _test() {
437 | _ = self(Array.self) as Output
438 | }
439 |
440 | }
441 |
442 | public protocol EquatableVisitor: AssociatedTypeRequirementsVisitor {
443 | associatedtype Visitor = EquatableVisitor
444 | associatedtype Input = Equatable
445 | associatedtype Output
446 |
447 | func callAsFunction(_ value: T) -> Output
448 | }
449 |
450 | extension EquatableVisitor {
451 |
452 | @inline(never)
453 | @_optimize(none)
454 | public func _test() {
455 | _ = self(42) as Output
456 | }
457 |
458 | }
459 |
460 | public protocol EquatableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
461 | associatedtype Visitor = EquatableTypeVisitor
462 | associatedtype Input = Equatable
463 | associatedtype Output
464 |
465 | func callAsFunction(_ type: T.Type) -> Output
466 | }
467 |
468 | extension EquatableTypeVisitor {
469 |
470 | @inline(never)
471 | @_optimize(none)
472 | public func _test() {
473 | _ = self(Int.self) as Output
474 | }
475 |
476 | }
477 |
478 | public protocol SequenceVisitor: AssociatedTypeRequirementsVisitor {
479 | associatedtype Visitor = SequenceVisitor
480 | associatedtype Input = Sequence
481 | associatedtype Output
482 |
483 | func callAsFunction(_ value: T) -> Output
484 | }
485 |
486 | extension SequenceVisitor {
487 |
488 | @inline(never)
489 | @_optimize(none)
490 | public func _test() {
491 | _ = self([42]) as Output
492 | }
493 |
494 | }
495 |
496 | public protocol SequenceTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
497 | associatedtype Visitor = SequenceTypeVisitor
498 | associatedtype Input = Sequence
499 | associatedtype Output
500 |
501 | func callAsFunction(_ type: T.Type) -> Output
502 | }
503 |
504 | extension SequenceTypeVisitor {
505 |
506 | @inline(never)
507 | @_optimize(none)
508 | public func _test() {
509 | _ = self(Array.self) as Output
510 | }
511 |
512 | }
513 |
514 | public protocol IteratorProtocolVisitor: AssociatedTypeRequirementsVisitor {
515 | associatedtype Visitor = IteratorProtocolVisitor
516 | associatedtype Input = IteratorProtocol
517 | associatedtype Output
518 |
519 | func callAsFunction(_ value: T) -> Output
520 | }
521 |
522 | extension IteratorProtocolVisitor {
523 |
524 | @inline(never)
525 | @_optimize(none)
526 | public func _test() {
527 | _ = self([42].makeIterator()) as Output
528 | }
529 |
530 | }
531 |
532 | public protocol IteratorProtocolTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
533 | associatedtype Visitor = IteratorProtocolTypeVisitor
534 | associatedtype Input = IteratorProtocol
535 | associatedtype Output
536 |
537 | func callAsFunction(_ type: T.Type) -> Output
538 | }
539 |
540 | extension IteratorProtocolTypeVisitor {
541 |
542 | @inline(never)
543 | @_optimize(none)
544 | public func _test() {
545 | _ = self(Array.Iterator.self) as Output
546 | }
547 |
548 | }
549 |
550 | public protocol UnsignedIntegerVisitor: AssociatedTypeRequirementsVisitor {
551 | associatedtype Visitor = UnsignedIntegerVisitor
552 | associatedtype Input = UnsignedInteger
553 | associatedtype Output
554 |
555 | func callAsFunction(_ value: T) -> Output
556 | }
557 |
558 | extension UnsignedIntegerVisitor {
559 |
560 | @inline(never)
561 | @_optimize(none)
562 | public func _test() {
563 | _ = self(42 as UInt) as Output
564 | }
565 |
566 | }
567 |
568 | public protocol UnsignedIntegerTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
569 | associatedtype Visitor = UnsignedIntegerTypeVisitor
570 | associatedtype Input = UnsignedInteger
571 | associatedtype Output
572 |
573 | func callAsFunction(_ type: T.Type) -> Output
574 | }
575 |
576 | extension UnsignedIntegerTypeVisitor {
577 |
578 | @inline(never)
579 | @_optimize(none)
580 | public func _test() {
581 | _ = self(UInt.self) as Output
582 | }
583 |
584 | }
585 |
586 | public protocol RangeExpressionVisitor: AssociatedTypeRequirementsVisitor {
587 | associatedtype Visitor = RangeExpressionVisitor
588 | associatedtype Input = RangeExpression
589 | associatedtype Output
590 |
591 | func callAsFunction(_ value: T) -> Output
592 | }
593 |
594 | extension RangeExpressionVisitor {
595 |
596 | @inline(never)
597 | @_optimize(none)
598 | public func _test() {
599 | _ = self(0..<1) as Output
600 | }
601 |
602 | }
603 |
604 | public protocol RangeExpressionTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
605 | associatedtype Visitor = RangeExpressionTypeVisitor
606 | associatedtype Input = RangeExpression
607 | associatedtype Output
608 |
609 | func callAsFunction(_ type: T.Type) -> Output
610 | }
611 |
612 | extension RangeExpressionTypeVisitor {
613 |
614 | @inline(never)
615 | @_optimize(none)
616 | public func _test() {
617 | _ = self(Range.self) as Output
618 | }
619 |
620 | }
621 |
622 | public protocol StrideableVisitor: AssociatedTypeRequirementsVisitor {
623 | associatedtype Visitor = StrideableVisitor
624 | associatedtype Input = Strideable
625 | associatedtype Output
626 |
627 | func callAsFunction(_ value: T) -> Output
628 | }
629 |
630 | extension StrideableVisitor {
631 |
632 | @inline(never)
633 | @_optimize(none)
634 | public func _test() {
635 | _ = self(42.0) as Output
636 | }
637 |
638 | }
639 |
640 | public protocol StrideableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
641 | associatedtype Visitor = StrideableTypeVisitor
642 | associatedtype Input = Strideable
643 | associatedtype Output
644 |
645 | func callAsFunction(_ type: T.Type) -> Output
646 | }
647 |
648 | extension StrideableTypeVisitor {
649 |
650 | @inline(never)
651 | @_optimize(none)
652 | public func _test() {
653 | _ = self(Double.self) as Output
654 | }
655 |
656 | }
657 |
658 | public protocol RawRepresentableVisitor: AssociatedTypeRequirementsVisitor {
659 | associatedtype Visitor = RawRepresentableVisitor
660 | associatedtype Input = RawRepresentable
661 | associatedtype Output
662 |
663 | func callAsFunction(_ value: T) -> Output
664 | }
665 |
666 | extension RawRepresentableVisitor {
667 |
668 | @inline(never)
669 | @_optimize(none)
670 | public func _test() {
671 | _ = self(TestRawRepresentable.test) as Output
672 | }
673 |
674 | }
675 |
676 | public protocol RawRepresentableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
677 | associatedtype Visitor = RawRepresentableTypeVisitor
678 | associatedtype Input = RawRepresentable
679 | associatedtype Output
680 |
681 | func callAsFunction(_ type: T.Type) -> Output
682 | }
683 |
684 | extension RawRepresentableTypeVisitor {
685 |
686 | @inline(never)
687 | @_optimize(none)
688 | public func _test() {
689 | _ = self(TestRawRepresentable.self.self) as Output
690 | }
691 |
692 | }
693 |
694 | public protocol StringProtocolVisitor: AssociatedTypeRequirementsVisitor {
695 | associatedtype Visitor = StringProtocolVisitor
696 | associatedtype Input = StringProtocol
697 | associatedtype Output
698 |
699 | func callAsFunction(_ value: T) -> Output
700 | }
701 |
702 | extension StringProtocolVisitor {
703 |
704 | @inline(never)
705 | @_optimize(none)
706 | public func _test() {
707 | _ = self("") as Output
708 | }
709 |
710 | }
711 |
712 | public protocol StringProtocolTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
713 | associatedtype Visitor = StringProtocolTypeVisitor
714 | associatedtype Input = StringProtocol
715 | associatedtype Output
716 |
717 | func callAsFunction(_ type: T.Type) -> Output
718 | }
719 |
720 | extension StringProtocolTypeVisitor {
721 |
722 | @inline(never)
723 | @_optimize(none)
724 | public func _test() {
725 | _ = self(String.self) as Output
726 | }
727 |
728 | }
729 |
730 | public protocol SignedIntegerVisitor: AssociatedTypeRequirementsVisitor {
731 | associatedtype Visitor = SignedIntegerVisitor
732 | associatedtype Input = SignedInteger
733 | associatedtype Output
734 |
735 | func callAsFunction(_ value: T) -> Output
736 | }
737 |
738 | extension SignedIntegerVisitor {
739 |
740 | @inline(never)
741 | @_optimize(none)
742 | public func _test() {
743 | _ = self(42) as Output
744 | }
745 |
746 | }
747 |
748 | public protocol SignedIntegerTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
749 | associatedtype Visitor = SignedIntegerTypeVisitor
750 | associatedtype Input = SignedInteger
751 | associatedtype Output
752 |
753 | func callAsFunction(_ type: T.Type) -> Output
754 | }
755 |
756 | extension SignedIntegerTypeVisitor {
757 |
758 | @inline(never)
759 | @_optimize(none)
760 | public func _test() {
761 | _ = self(Int.self) as Output
762 | }
763 |
764 | }
765 |
766 | public protocol BinaryIntegerVisitor: AssociatedTypeRequirementsVisitor {
767 | associatedtype Visitor = BinaryIntegerVisitor
768 | associatedtype Input = BinaryInteger
769 | associatedtype Output
770 |
771 | func callAsFunction(_ value: T) -> Output
772 | }
773 |
774 | extension BinaryIntegerVisitor {
775 |
776 | @inline(never)
777 | @_optimize(none)
778 | public func _test() {
779 | _ = self(42) as Output
780 | }
781 |
782 | }
783 |
784 | public protocol BinaryIntegerTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
785 | associatedtype Visitor = BinaryIntegerTypeVisitor
786 | associatedtype Input = BinaryInteger
787 | associatedtype Output
788 |
789 | func callAsFunction(_ type: T.Type) -> Output
790 | }
791 |
792 | extension BinaryIntegerTypeVisitor {
793 |
794 | @inline(never)
795 | @_optimize(none)
796 | public func _test() {
797 | _ = self(Int.self) as Output
798 | }
799 |
800 | }
801 |
802 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
803 | public protocol IdentifiableVisitor: AssociatedTypeRequirementsVisitor {
804 | associatedtype Visitor = IdentifiableVisitor
805 | associatedtype Input = Identifiable
806 | associatedtype Output
807 |
808 | func callAsFunction(_ value: T) -> Output
809 | }
810 |
811 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
812 | extension IdentifiableVisitor {
813 |
814 | @inline(never)
815 | @_optimize(none)
816 | public func _test() {
817 | _ = self(TestIdentifiable(id: "test")) as Output
818 | }
819 |
820 | }
821 |
822 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
823 | public protocol IdentifiableTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
824 | associatedtype Visitor = IdentifiableTypeVisitor
825 | associatedtype Input = Identifiable
826 | associatedtype Output
827 |
828 | func callAsFunction(_ type: T.Type) -> Output
829 | }
830 |
831 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
832 | extension IdentifiableTypeVisitor {
833 |
834 | @inline(never)
835 | @_optimize(none)
836 | public func _test() {
837 | _ = self(TestIdentifiable.self) as Output
838 | }
839 |
840 | }
841 |
842 | #endif
843 |
844 | // SwiftUI
845 | #if canImport(SwiftUI)
846 | import SwiftUI
847 |
848 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
849 | public protocol ViewVisitor: AssociatedTypeRequirementsVisitor {
850 | associatedtype Visitor = ViewVisitor
851 | associatedtype Input = View
852 | associatedtype Output
853 |
854 | func callAsFunction(_ value: T) -> Output
855 | }
856 |
857 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
858 | extension ViewVisitor {
859 |
860 | @inline(never)
861 | @_optimize(none)
862 | public func _test() {
863 | _ = self(EmptyView()) as Output
864 | }
865 |
866 | }
867 |
868 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
869 | public protocol ViewTypeVisitor: AssociatedTypeRequirementsTypeVisitor {
870 | associatedtype Visitor = ViewTypeVisitor
871 | associatedtype Input = View
872 | associatedtype Output
873 |
874 | func callAsFunction(_ type: T.Type) -> Output
875 | }
876 |
877 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
878 | extension ViewTypeVisitor {
879 |
880 | @inline(never)
881 | @_optimize(none)
882 | public func _test() {
883 | _ = self(EmptyView.self) as Output
884 | }
885 |
886 | }
887 |
888 | #endif
889 |
--------------------------------------------------------------------------------
/Sources/AssociatedTypeRequirementsVisitor/visitors.swift.gyb:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import ProtocolType
4 |
5 | %{
6 | import json
7 |
8 | modules = []
9 | with open('../../commonProtocols.json') as file:
10 | modules = json.loads(file.read())
11 | }%
12 | % for module in modules:
13 | %{ moduleName = module['module'] }%
14 |
15 | // ${moduleName}
16 | #if canImport(${moduleName})
17 | import ${moduleName}
18 |
19 | % for type in module['types']:
20 | %{ typeName = type['name'] }%
21 | % if 'availability' in module:
22 | ${module['availability']}
23 | % elif 'availability' in type:
24 | ${type['availability']}
25 | % end
26 | public protocol ${typeName}Visitor: AssociatedTypeRequirementsVisitor {
27 | associatedtype Visitor = ${typeName}Visitor
28 | associatedtype Input = ${typeName}
29 | associatedtype Output
30 |
31 | func callAsFunction(_ value: T) -> Output
32 | }
33 |
34 | % if 'availability' in module:
35 | ${module['availability']}
36 | % elif 'availability' in type:
37 | ${type['availability']}
38 | % end
39 | extension ${typeName}Visitor {
40 |
41 | @inline(never)
42 | @_optimize(none)
43 | public func _test() {
44 | _ = self(${type['testValue']}) as Output
45 | }
46 |
47 | }
48 |
49 | % if 'availability' in module:
50 | ${module['availability']}
51 | % elif 'availability' in type:
52 | ${type['availability']}
53 | % end
54 | public protocol ${typeName}TypeVisitor: AssociatedTypeRequirementsTypeVisitor {
55 | associatedtype Visitor = ${typeName}TypeVisitor
56 | associatedtype Input = ${typeName}
57 | associatedtype Output
58 |
59 | func callAsFunction(_ type: T.Type) -> Output
60 | }
61 |
62 | % if 'availability' in module:
63 | ${module['availability']}
64 | % elif 'availability' in type:
65 | ${type['availability']}
66 | % end
67 | extension ${typeName}TypeVisitor {
68 |
69 | @inline(never)
70 | @_optimize(none)
71 | public func _test() {
72 | _ = self(${type['testType']}.self) as Output
73 | }
74 |
75 | }
76 |
77 | % end
78 | #endif
79 | % end
80 |
--------------------------------------------------------------------------------
/Sources/CContext/CContext.c:
--------------------------------------------------------------------------------
1 |
2 | void set_self_pointer(void *pointer) {
3 | #ifdef __aarch64__
4 | __asm__("mov x20, x0");
5 | #endif
6 | #ifdef __x86_64__
7 | __asm__("movq %rdi, %r13");
8 | #endif
9 | }
10 |
--------------------------------------------------------------------------------
/Sources/CContext/include/CContext.h:
--------------------------------------------------------------------------------
1 |
2 | void set_self_pointer(void *pointer);
3 |
--------------------------------------------------------------------------------
/Sources/Casting/CastedProtocolValue.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import ProtocolConformance
4 |
5 | public struct CastedProtocolValue {
6 | let value: UnsafeRawPointer
7 | let conformanceRecord: ProtocolConformanceRecord
8 | }
9 |
--------------------------------------------------------------------------------
/Sources/Casting/withCasted.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import ProtocolConformance
4 | import ProtocolType
5 | import ValuePointers
6 |
7 | public func withCasted(_ value: Any, as moduleName: ModuleName, _ protocolName: ProtocolName, body: (CastedProtocolValue) throws -> Result) rethrows -> Result? {
8 | guard let protocolType = ProtocolType(moduleName: moduleName, protocolName: protocolName) else { return nil }
9 | return try withCasted(value, as: protocolType, body: body)
10 | }
11 |
12 | public func withCasted(_ value: Any, as protocolType: ProtocolType, body: (CastedProtocolValue) throws -> Result) rethrows -> Result? {
13 | return try withCasted(value, as: protocolType.type, body: body)
14 | }
15 |
16 | public func withCasted(_ value: Any, as protocolType: Any.Type, body: (CastedProtocolValue) throws -> Result) rethrows -> Result? {
17 | let implementationType = type(of: value)
18 | guard let conformanceRecord = ProtocolConformanceRecord(implementationType: implementationType, protocolType: protocolType) else { return nil }
19 | return try withUnsafeValuePointer(to: value) { try body(CastedProtocolValue(value: $0, conformanceRecord: conformanceRecord)) }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ProtocolConformance/ProtocolConformanceRecord.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 | import ProtocolType
4 |
5 | // MARK: Getting the conformance record
6 |
7 | public struct ProtocolConformanceRecord {
8 | public let type: Any.Type
9 | public let witnessTable: UnsafeRawPointer?
10 | }
11 |
12 | extension ProtocolConformanceRecord {
13 |
14 | public init?(implementationType: Any.Type, protocolType: Any.Type) {
15 | let metadata = ProtocolMetadata(type: protocolType)
16 | guard let witnessTable = _conformsToProtocol(implementationType, metadata.protocolDescriptorVector) else { return nil }
17 | self.init(type: implementationType, witnessTable: witnessTable)
18 | }
19 |
20 | }
21 |
22 | extension ProtocolConformanceRecord {
23 |
24 | public init?(implementationType: Any.Type, protocolType: ProtocolType) {
25 | self.init(implementationType: implementationType, protocolType: protocolType.type)
26 | }
27 |
28 | }
29 |
30 | // MARK: - Checking for conformance
31 |
32 | public func does(_ implementationType: Any.Type, conformTo protocolType: Any.Type) -> Bool {
33 | let metadata = ProtocolMetadata(type: protocolType)
34 | return _conformsToProtocol(implementationType, metadata.protocolDescriptorVector) != nil
35 | }
36 |
37 | public func does(_ implementationType: Any.Type, conformTo protocolType: ProtocolType) -> Bool {
38 | return does(implementationType, conformTo: protocolType.type)
39 | }
40 |
41 | // MARK: - Structure of Protocol Metadata
42 |
43 | private struct ProtocolDescriptor { }
44 |
45 | private struct ProtocolMetadata {
46 | let kind: Int
47 | let layoutFlags: UInt32
48 | let numberOfProtocols: UInt32
49 | let protocolDescriptorVector: UnsafeMutablePointer
50 |
51 | init(type: Any.Type) {
52 | self = unsafeBitCast(type, to: UnsafeMutablePointer.self).pointee
53 | }
54 | }
55 |
56 | // MARK: - Runtime functions
57 |
58 | @_silgen_name("swift_conformsToProtocol")
59 | private func _conformsToProtocol(
60 | _ type: Any.Type,
61 | _ protocolDescriptor: UnsafeMutablePointer
62 | ) -> UnsafeRawPointer?
63 |
--------------------------------------------------------------------------------
/Sources/ProtocolConformance/fakeConformance.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | public func fakeConformance(_ type: Any.Type, as protocolType: T.Type = T.self) -> T {
5 | let conformance = ProtocolConformanceRecord(type: type, witnessTable: nil)
6 | return unsafeBitCast(conformance, to: protocolType)
7 | }
8 |
--------------------------------------------------------------------------------
/Sources/ProtocolConformance/helpers.swift:
--------------------------------------------------------------------------------
1 |
2 | import ProtocolType
3 |
4 | // Swift
5 | public func isBinaryFloatingPoint(_ type: Any.Type) -> Bool {
6 | return does(type, conformTo: .binaryFloatingPoint)
7 | }
8 |
9 | public func isEncodable(_ type: Any.Type) -> Bool {
10 | return does(type, conformTo: .encodable)
11 | }
12 |
13 | public func isDecodable(_ type: Any.Type) -> Bool {
14 | return does(type, conformTo: .decodable)
15 | }
16 |
17 | public func isRandomNumberGenerator(_ type: Any.Type) -> Bool {
18 | return does(type, conformTo: .randomNumberGenerator)
19 | }
20 |
21 | public func isHashable(_ type: Any.Type) -> Bool {
22 | return does(type, conformTo: .hashable)
23 | }
24 |
25 | public func isNumeric(_ type: Any.Type) -> Bool {
26 | return does(type, conformTo: .numeric)
27 | }
28 |
29 | public func isBidirectionalCollection(_ type: Any.Type) -> Bool {
30 | return does(type, conformTo: .bidirectionalCollection)
31 | }
32 |
33 | public func isRandomAccessCollection(_ type: Any.Type) -> Bool {
34 | return does(type, conformTo: .randomAccessCollection)
35 | }
36 |
37 | public func isComparable(_ type: Any.Type) -> Bool {
38 | return does(type, conformTo: .comparable)
39 | }
40 |
41 | public func isCollection(_ type: Any.Type) -> Bool {
42 | return does(type, conformTo: .collection)
43 | }
44 |
45 | public func isMutableCollection(_ type: Any.Type) -> Bool {
46 | return does(type, conformTo: .mutableCollection)
47 | }
48 |
49 | public func isRangeReplaceableCollection(_ type: Any.Type) -> Bool {
50 | return does(type, conformTo: .rangeReplaceableCollection)
51 | }
52 |
53 | public func isEquatable(_ type: Any.Type) -> Bool {
54 | return does(type, conformTo: .equatable)
55 | }
56 |
57 | public func isSequence(_ type: Any.Type) -> Bool {
58 | return does(type, conformTo: .sequence)
59 | }
60 |
61 | public func isIteratorProtocol(_ type: Any.Type) -> Bool {
62 | return does(type, conformTo: .iteratorProtocol)
63 | }
64 |
65 | public func isUnsignedInteger(_ type: Any.Type) -> Bool {
66 | return does(type, conformTo: .unsignedInteger)
67 | }
68 |
69 | public func isRangeExpression(_ type: Any.Type) -> Bool {
70 | return does(type, conformTo: .rangeExpression)
71 | }
72 |
73 | public func isStrideable(_ type: Any.Type) -> Bool {
74 | return does(type, conformTo: .strideable)
75 | }
76 |
77 | public func isRawRepresentable(_ type: Any.Type) -> Bool {
78 | return does(type, conformTo: .rawRepresentable)
79 | }
80 |
81 | public func isStringProtocol(_ type: Any.Type) -> Bool {
82 | return does(type, conformTo: .stringProtocol)
83 | }
84 |
85 | public func isSignedInteger(_ type: Any.Type) -> Bool {
86 | return does(type, conformTo: .signedInteger)
87 | }
88 |
89 | public func isBinaryInteger(_ type: Any.Type) -> Bool {
90 | return does(type, conformTo: .binaryInteger)
91 | }
92 |
93 | public func isIdentifiable(_ type: Any.Type) -> Bool {
94 | return does(type, conformTo: .identifiable)
95 | }
96 |
97 | // SwiftUI
98 | public func isView(_ type: Any.Type) -> Bool {
99 | return does(type, conformTo: .view)
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/Sources/ProtocolConformance/helpers.swift.gyb:
--------------------------------------------------------------------------------
1 |
2 | import ProtocolType
3 |
4 | %{
5 | import json
6 |
7 | modules = []
8 | with open('../../commonProtocols.json') as file:
9 | modules = json.loads(file.read())
10 | }%
11 | % for module in modules:
12 | // ${module['module']}
13 | % for type in module['types']:
14 | %{ name = type['name'] }%
15 | public func is${name}(_ type: Any.Type) -> Bool {
16 | return does(type, conformTo: .${name[0].lower()}${name[1:]})
17 | }
18 |
19 | % end
20 | % end
21 |
--------------------------------------------------------------------------------
/Sources/ProtocolType/ModuleName.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | public struct ModuleName : RawRepresentable, Equatable {
5 | public let rawValue: String
6 |
7 | public init(rawValue: String) {
8 | self.rawValue = rawValue
9 | }
10 | }
11 |
12 | extension ModuleName : ExpressibleByStringLiteral {
13 |
14 | public init(stringLiteral value: String) {
15 | self.init(rawValue: value)
16 | }
17 |
18 | }
19 |
20 |
21 | extension ModuleName {
22 |
23 | public static let swift: ModuleName = "Swift"
24 | public static let swiftUI: ModuleName = "SwiftUI"
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/ProtocolType/ModuleName.swift.gyb:
--------------------------------------------------------------------------------
1 |
2 | %{
3 | import json
4 |
5 | modules = []
6 | with open('../../commonProtocols.json') as file:
7 | modules = json.loads(file.read())
8 | }%
9 | import Foundation
10 |
11 | public struct ModuleName : RawRepresentable, Equatable {
12 | public let rawValue: String
13 |
14 | public init(rawValue: String) {
15 | self.rawValue = rawValue
16 | }
17 | }
18 |
19 | extension ModuleName : ExpressibleByStringLiteral {
20 |
21 | public init(stringLiteral value: String) {
22 | self.init(rawValue: value)
23 | }
24 |
25 | }
26 |
27 |
28 | extension ModuleName {
29 |
30 | % for module in modules:
31 | %{ name = module['module'] }%
32 | public static let ${name[0].lower()}${name[1:]}: ModuleName = "${name}"
33 | % end
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/ProtocolType/ProtocolName.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | public struct ProtocolName : RawRepresentable, Equatable {
5 | public let rawValue: String
6 |
7 | public init(rawValue: String) {
8 | self.rawValue = rawValue
9 | }
10 | }
11 |
12 | extension ProtocolName : ExpressibleByStringLiteral {
13 |
14 | public init(stringLiteral value: String) {
15 | self.init(rawValue: value)
16 | }
17 |
18 | }
19 |
20 | extension ProtocolName {
21 |
22 | // Swift
23 | public static let binaryFloatingPoint: ProtocolName = "BinaryFloatingPoint"
24 | public static let encodable: ProtocolName = "Encodable"
25 | public static let decodable: ProtocolName = "Decodable"
26 | public static let randomNumberGenerator: ProtocolName = "RandomNumberGenerator"
27 | public static let hashable: ProtocolName = "Hashable"
28 | public static let numeric: ProtocolName = "Numeric"
29 | public static let bidirectionalCollection: ProtocolName = "BidirectionalCollection"
30 | public static let randomAccessCollection: ProtocolName = "RandomAccessCollection"
31 | public static let comparable: ProtocolName = "Comparable"
32 | public static let collection: ProtocolName = "Collection"
33 | public static let mutableCollection: ProtocolName = "MutableCollection"
34 | public static let rangeReplaceableCollection: ProtocolName = "RangeReplaceableCollection"
35 | public static let equatable: ProtocolName = "Equatable"
36 | public static let sequence: ProtocolName = "Sequence"
37 | public static let iteratorProtocol: ProtocolName = "IteratorProtocol"
38 | public static let unsignedInteger: ProtocolName = "UnsignedInteger"
39 | public static let rangeExpression: ProtocolName = "RangeExpression"
40 | public static let strideable: ProtocolName = "Strideable"
41 | public static let rawRepresentable: ProtocolName = "RawRepresentable"
42 | public static let stringProtocol: ProtocolName = "StringProtocol"
43 | public static let signedInteger: ProtocolName = "SignedInteger"
44 | public static let binaryInteger: ProtocolName = "BinaryInteger"
45 | public static let identifiable: ProtocolName = "Identifiable"
46 |
47 | // SwiftUI
48 | public static let view: ProtocolName = "View"
49 | }
50 |
--------------------------------------------------------------------------------
/Sources/ProtocolType/ProtocolName.swift.gyb:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | %{
5 | import json
6 |
7 | modules = []
8 | with open('../../commonProtocols.json') as file:
9 | modules = json.loads(file.read())
10 | }%
11 | public struct ProtocolName : RawRepresentable, Equatable {
12 | public let rawValue: String
13 |
14 | public init(rawValue: String) {
15 | self.rawValue = rawValue
16 | }
17 | }
18 |
19 | extension ProtocolName : ExpressibleByStringLiteral {
20 |
21 | public init(stringLiteral value: String) {
22 | self.init(rawValue: value)
23 | }
24 |
25 | }
26 |
27 | extension ProtocolName {
28 | % for module in modules:
29 |
30 | // ${module['module']}
31 | % for type in module['types']:
32 | %{ name = type['name'] }%
33 | public static let ${name[0].lower()}${name[1:]}: ProtocolName = "${name}"
34 | % end
35 | % end
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/ProtocolType/ProtocolType.swift:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | public struct ProtocolType {
5 | public let type: Any.Type
6 |
7 | public init?(moduleName: ModuleName, protocolName: ProtocolName) {
8 | let name = mangledName(moduleName: moduleName, protocolName: protocolName)
9 | guard let type = _typeByName(name) else { return nil }
10 | self.type = type
11 | }
12 | }
13 |
14 | extension ProtocolType {
15 |
16 | // Swift
17 | public static let binaryFloatingPoint = ProtocolType(moduleName: .swift, protocolName: .binaryFloatingPoint)!
18 | public static let encodable = ProtocolType(moduleName: .swift, protocolName: .encodable)!
19 | public static let decodable = ProtocolType(moduleName: .swift, protocolName: .decodable)!
20 | public static let randomNumberGenerator = ProtocolType(moduleName: .swift, protocolName: .randomNumberGenerator)!
21 | public static let hashable = ProtocolType(moduleName: .swift, protocolName: .hashable)!
22 | public static let numeric = ProtocolType(moduleName: .swift, protocolName: .numeric)!
23 | public static let bidirectionalCollection = ProtocolType(moduleName: .swift, protocolName: .bidirectionalCollection)!
24 | public static let randomAccessCollection = ProtocolType(moduleName: .swift, protocolName: .randomAccessCollection)!
25 | public static let comparable = ProtocolType(moduleName: .swift, protocolName: .comparable)!
26 | public static let collection = ProtocolType(moduleName: .swift, protocolName: .collection)!
27 | public static let mutableCollection = ProtocolType(moduleName: .swift, protocolName: .mutableCollection)!
28 | public static let rangeReplaceableCollection = ProtocolType(moduleName: .swift, protocolName: .rangeReplaceableCollection)!
29 | public static let equatable = ProtocolType(moduleName: .swift, protocolName: .equatable)!
30 | public static let sequence = ProtocolType(moduleName: .swift, protocolName: .sequence)!
31 | public static let iteratorProtocol = ProtocolType(moduleName: .swift, protocolName: .iteratorProtocol)!
32 | public static let unsignedInteger = ProtocolType(moduleName: .swift, protocolName: .unsignedInteger)!
33 | public static let rangeExpression = ProtocolType(moduleName: .swift, protocolName: .rangeExpression)!
34 | public static let strideable = ProtocolType(moduleName: .swift, protocolName: .strideable)!
35 | public static let rawRepresentable = ProtocolType(moduleName: .swift, protocolName: .rawRepresentable)!
36 | public static let stringProtocol = ProtocolType(moduleName: .swift, protocolName: .stringProtocol)!
37 | public static let signedInteger = ProtocolType(moduleName: .swift, protocolName: .signedInteger)!
38 | public static let binaryInteger = ProtocolType(moduleName: .swift, protocolName: .binaryInteger)!
39 | public static let identifiable = ProtocolType(moduleName: .swift, protocolName: .identifiable)!
40 |
41 | // SwiftUI
42 | public static let view = ProtocolType(moduleName: .swiftUI, protocolName: .view)!
43 |
44 | }
45 |
46 | private func mangledName(moduleName: ModuleName, protocolName: ProtocolName) -> String {
47 |
48 | switch moduleName {
49 | case .swift:
50 | switch protocolName {
51 | case .encodable:
52 | return "SE"
53 | case .decodable:
54 | return "Sd"
55 | case .randomNumberGenerator:
56 | return "SG"
57 | case .hashable:
58 | return "SH"
59 | case .numeric:
60 | return "Sj"
61 | case .bidirectionalCollection:
62 | return "SK"
63 | case .randomAccessCollection:
64 | return "Sk"
65 | case .comparable:
66 | return "SL"
67 | case .mutableCollection:
68 | return "SM"
69 | case .rangeReplaceableCollection:
70 | return "Sm"
71 | case .equatable:
72 | return "SQ"
73 | case .sequence:
74 | return "ST"
75 | case .iteratorProtocol:
76 | return "St"
77 | case .unsignedInteger:
78 | return "SU"
79 | case .rangeExpression:
80 | return "SX"
81 | case .strideable:
82 | return "Sx"
83 | case .stringProtocol:
84 | return "Sy"
85 | case .signedInteger:
86 | return "SZ"
87 | case .binaryInteger:
88 | return "Sz"
89 | default:
90 | break
91 | }
92 | default:
93 | break
94 | }
95 |
96 | return "\(moduleName.rawValue.count)\(moduleName.rawValue)\(protocolName.rawValue.count)\(protocolName.rawValue)_p"
97 | }
98 |
--------------------------------------------------------------------------------
/Sources/ProtocolType/ProtocolType.swift.gyb:
--------------------------------------------------------------------------------
1 |
2 | import Foundation
3 |
4 | %{
5 | import json
6 |
7 | modules = []
8 | with open('../../commonProtocols.json') as file:
9 | modules = json.loads(file.read())
10 | }%
11 | public struct ProtocolType {
12 | public let type: Any.Type
13 |
14 | public init?(moduleName: ModuleName, protocolName: ProtocolName) {
15 | let name = mangledName(moduleName: moduleName, protocolName: protocolName)
16 | guard let type = _typeByName(name) else { return nil }
17 | self.type = type
18 | }
19 | }
20 |
21 | extension ProtocolType {
22 | % for module in modules:
23 | %{ moduleName = module['module'] }%
24 |
25 | // ${moduleName}
26 | % for type in module['types']:
27 | %{ typeName = type['name'] }%
28 | public static let ${typeName[0].lower()}${typeName[1:]} = ProtocolType(moduleName: .${moduleName[0].lower()}${moduleName[1:]}, protocolName: .${typeName[0].lower()}${typeName[1:]})!
29 | % end
30 | % end
31 |
32 | }
33 |
34 | private func mangledName(moduleName: ModuleName, protocolName: ProtocolName) -> String {
35 |
36 | switch moduleName {
37 | % for module in modules:
38 | %{ moduleName = module['module'] }%
39 | %{ specialCases = [type for type in module['types'] if 'mangledShorthand' in type] }%
40 | % if len(specialCases) > 0:
41 | case .${moduleName[0].lower()}${moduleName[1:]}:
42 | switch protocolName {
43 | % for type in specialCases:
44 | %{ typeName = type['name'] }%
45 | case .${typeName[0].lower()}${typeName[1:]}:
46 | return "${type['mangledShorthand']}"
47 | % end
48 | default:
49 | break
50 | }
51 | % end
52 | % end
53 | default:
54 | break
55 | }
56 |
57 | return "\(moduleName.rawValue.count)\(moduleName.rawValue)\(protocolName.rawValue.count)\(protocolName.rawValue)_p"
58 | }
59 |
--------------------------------------------------------------------------------
/Sources/ValuePointers/withUnsafeValuePointer.swift:
--------------------------------------------------------------------------------
1 |
2 |
3 | import Foundation
4 | import ProtocolConformance
5 |
6 | /// Pointer to actual value without knowing the type at compile time. It will point to the correct part no matter how it's internal memory works
7 | public func withUnsafeValuePointer(to value: Any, body: (UnsafeRawPointer) throws -> Result) rethrows -> Result {
8 | return try pointable(for: type(of: value)).withUnsafeRawPointer(to: value, body: body)
9 | }
10 |
11 | /// Bytes of the actual value without knowing the value at compile time, even when it doesn't fit in the 32 bytes of Any
12 | public func withUnsafeValueBytes(of value: Any, body: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
13 | return try pointable(for: type(of: value)).withUnsafeRawBytes(of: value, body: body)
14 | }
15 |
16 | private func pointable(for type: Any.Type) -> Pointable.Type {
17 | return fakeConformance(type)
18 | }
19 |
20 | private protocol Pointable { }
21 | extension Pointable {
22 | static func withUnsafeRawPointer(to value: Any, body: (UnsafeRawPointer) throws -> Result) rethrows -> Result {
23 | return try withUnsafePointer(to: value as! Self) { try body(UnsafeRawPointer($0)) }
24 | }
25 |
26 | static func withUnsafeRawBytes(of value: Any, body: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
27 | return try withUnsafeBytes(of: value as! Self, body)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Tests/AssociatedTypeRequirementsKitTests/ProtocolTypeTests.swift:
--------------------------------------------------------------------------------
1 |
2 | import XCTest
3 | import ProtocolType
4 |
5 | final class ProtocolTypeTests: XCTestCase {
6 | func testTypeIsResolved() {
7 | let type = ProtocolType(moduleName: "AssociatedTypeRequirementsKitTests", protocolName: "TestProtocol")
8 | XCTAssertNotNil(type)
9 | }
10 |
11 | func testWrongTypeIsNil() {
12 | let type = ProtocolType(moduleName: "AssociatedTypeRequirementsKitTests", protocolName: "SomeType")
13 | XCTAssertNil(type)
14 | }
15 | }
16 |
17 | protocol TestProtocol { }
18 |
--------------------------------------------------------------------------------
/Tests/AssociatedTypeRequirementsKitTests/ValuePointersTests.swift:
--------------------------------------------------------------------------------
1 |
2 | import XCTest
3 | import ValuePointers
4 |
5 | final class ValuePointersTests: XCTestCase {
6 | struct BigStruct {
7 | let first: String
8 | let second: String
9 | let third: String
10 | let fourth: String
11 | let fifth: String
12 | let sixth: String
13 | }
14 |
15 | func testBytesAreCorrect() {
16 | let value = BigStruct(first: "1", second: "2", third: "3", fourth: "4", fifth: "5", sixth: "6")
17 | let normalCount = withUnsafeBytes(of: value) { $0.count }
18 | let anyCount = withUnsafeBytes(of: value as Any) { $0.count }
19 | let ourCount = withUnsafeValueBytes(of: value) { $0.count }
20 |
21 | XCTAssertNotEqual(normalCount, anyCount)
22 | XCTAssertEqual(normalCount, ourCount)
23 |
24 | let thirdString = withUnsafeValueBytes(of: value) { $0.baseAddress!.advanced(by: 2 * MemoryLayout.size).load(as: String.self) }
25 | XCTAssertEqual(thirdString, "3")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Tests/AssociatedTypeRequirementsKitTests/VisitorTests.swift:
--------------------------------------------------------------------------------
1 |
2 | import XCTest
3 | import AssociatedTypeRequirementsVisitor
4 |
5 | #if canImport(SwiftUI)
6 | import SwiftUI
7 | #endif
8 |
9 | final class VisitorTests: XCTestCase {
10 | func testVisitDecodableType() {
11 | let type: Any.Type = SomeDedecodable.self
12 | let json = """
13 | {
14 | "a": "A",
15 | "b": "B"
16 | }
17 | """
18 | let value = JSONDecoder().decodeIfPossible(type, from: json.data(using: .utf8)!)
19 | XCTAssertNotNil(value)
20 | }
21 |
22 | func testVisitHashable() {
23 | let value = "String"
24 | let hashed = value.hashValue
25 | let hasher = AnyHasher()
26 | let recledtedHash = hasher(value as Any)
27 | XCTAssertNotNil(recledtedHash)
28 | XCTAssertEqual(hashed, recledtedHash)
29 | }
30 |
31 | #if canImport(SwiftUI)
32 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
33 | func testVisitView() {
34 | let value: Any = Text("One two three four")
35 | let eraser = ViewTypeEraser()
36 | let anyView = eraser(value)
37 | XCTAssertNotNil(anyView)
38 | XCTAssertNil(eraser(123))
39 | }
40 | #endif
41 | }
42 |
43 | struct SomeDedecodable: Decodable {
44 | let a: String
45 | let b: String
46 | }
47 |
48 | extension JSONDecoder {
49 |
50 | func decodeIfPossible(_ type: Any.Type, from data: Data) -> Any? {
51 | let visitor = JSONDecoderVisitor(decoder: self, data: data)
52 | return visitor(type)
53 | }
54 |
55 | }
56 |
57 | private struct JSONDecoderVisitor: DecodableTypeVisitor {
58 | let decoder: JSONDecoder
59 | let data: Data
60 |
61 | func callAsFunction(_ type: T.Type) -> Any {
62 | return try! decoder.decode(type, from: data)
63 | }
64 | }
65 |
66 | struct AnyHasher: HashableVisitor {
67 | func callAsFunction(_ value: T) -> Int {
68 | var hasher = Hasher()
69 | value.hash(into: &hasher)
70 | return hasher.finalize()
71 | }
72 | }
73 |
74 | #if canImport(SwiftUI)
75 | @available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
76 | struct ViewTypeEraser: ViewVisitor {
77 |
78 | func callAsFunction(_ value: T) -> AnyView {
79 | if let value = value as? AnyView {
80 | return value
81 | }
82 | return AnyView(value)
83 | }
84 |
85 | }
86 | #endif
87 |
--------------------------------------------------------------------------------
/Tests/AssociatedTypeRequirementsKitTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | #if !canImport(ObjectiveC)
2 | import XCTest
3 |
4 | extension ProtocolTypeTests {
5 | // DO NOT MODIFY: This is autogenerated, use:
6 | // `swift test --generate-linuxmain`
7 | // to regenerate.
8 | static let __allTests__ProtocolTypeTests = [
9 | ("testTypeIsResolved", testTypeIsResolved),
10 | ("testWrongTypeIsNil", testWrongTypeIsNil),
11 | ]
12 | }
13 |
14 | extension ValuePointersTests {
15 | // DO NOT MODIFY: This is autogenerated, use:
16 | // `swift test --generate-linuxmain`
17 | // to regenerate.
18 | static let __allTests__ValuePointersTests = [
19 | ("testBytesAreCorrect", testBytesAreCorrect),
20 | ]
21 | }
22 |
23 | extension VisitorTests {
24 | // DO NOT MODIFY: This is autogenerated, use:
25 | // `swift test --generate-linuxmain`
26 | // to regenerate.
27 | static let __allTests__VisitorTests = [
28 | ("testVisitDecodableType", testVisitDecodableType),
29 | ("testVisitHashable", testVisitHashable),
30 | // ("testVisitView", testVisitView),
31 | ]
32 | }
33 |
34 | public func __allTests() -> [XCTestCaseEntry] {
35 | return [
36 | testCase(ProtocolTypeTests.__allTests__ProtocolTypeTests),
37 | testCase(ValuePointersTests.__allTests__ValuePointersTests),
38 | testCase(VisitorTests.__allTests__VisitorTests),
39 | ]
40 | }
41 | #endif
42 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import AssociatedTypeRequirementsKitTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += AssociatedTypeRequirementsKitTests.__allTests()
7 |
8 | XCTMain(tests)
9 |
--------------------------------------------------------------------------------
/commonProtocols.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "module" : "Swift",
4 | "types" : [
5 | {
6 | "name" : "BinaryFloatingPoint",
7 | "mangledName" : "SB",
8 | "testType": "Double",
9 | "testValue": "42.0"
10 | },
11 | {
12 | "name" : "Encodable",
13 | "mangledShorthand" : "SE",
14 | "testType": "Int",
15 | "testValue": "42"
16 | },
17 | {
18 | "name" : "Decodable",
19 | "mangledShorthand" : "Sd",
20 | "testType": "Int",
21 | "testValue": "42"
22 | },
23 | {
24 | "name" : "RandomNumberGenerator",
25 | "mangledShorthand" : "SG",
26 | "testType": "SystemRandomNumberGenerator",
27 | "testValue": "SystemRandomNumberGenerator()"
28 | },
29 | {
30 | "name" : "Hashable",
31 | "mangledShorthand" : "SH",
32 | "testType": "Int",
33 | "testValue": "42"
34 | },
35 | {
36 | "name" : "Numeric",
37 | "mangledShorthand" : "Sj",
38 | "testType": "Int",
39 | "testValue": "42"
40 | },
41 | {
42 | "name" : "BidirectionalCollection",
43 | "mangledShorthand" : "SK",
44 | "testType": "Array",
45 | "testValue": "[42]"
46 | },
47 | {
48 | "name" : "RandomAccessCollection",
49 | "mangledShorthand" : "Sk",
50 | "testType": "Array",
51 | "testValue": "[42]"
52 | },
53 | {
54 | "name" : "Comparable",
55 | "mangledShorthand" : "SL",
56 | "testType": "Int",
57 | "testValue": "42"
58 | },
59 | {
60 | "name" : "Collection",
61 | "mangledName" : "Sl",
62 | "testType": "Array",
63 | "testValue": "[42]"
64 | },
65 | {
66 | "name" : "MutableCollection",
67 | "mangledShorthand" : "SM",
68 | "testType": "Array",
69 | "testValue": "[42]"
70 | },
71 | {
72 | "name" : "RangeReplaceableCollection",
73 | "mangledShorthand" : "Sm",
74 | "testType": "Array",
75 | "testValue": "[42]"
76 | },
77 | {
78 | "name" : "Equatable",
79 | "mangledShorthand" : "SQ",
80 | "testType": "Int",
81 | "testValue": "42"
82 | },
83 | {
84 | "name" : "Sequence",
85 | "mangledShorthand" : "ST",
86 | "testType": "Array",
87 | "testValue": "[42]"
88 | },
89 | {
90 | "name" : "IteratorProtocol",
91 | "mangledShorthand" : "St",
92 | "testType": "Array.Iterator",
93 | "testValue": "[42].makeIterator()"
94 | },
95 | {
96 | "name" : "UnsignedInteger",
97 | "mangledShorthand" : "SU",
98 | "testType": "UInt",
99 | "testValue": "42 as UInt"
100 | },
101 | {
102 | "name" : "RangeExpression",
103 | "mangledShorthand" : "SX",
104 | "testType": "Range",
105 | "testValue": "0..<1"
106 | },
107 | {
108 | "name" : "Strideable",
109 | "mangledShorthand" : "Sx",
110 | "testType": "Double",
111 | "testValue": "42.0"
112 | },
113 | {
114 | "name" : "RawRepresentable",
115 | "mangledName" : "SY",
116 | "testType": "TestRawRepresentable.self",
117 | "testValue": "TestRawRepresentable.test"
118 | },
119 | {
120 | "name" : "StringProtocol",
121 | "mangledShorthand" : "Sy",
122 | "testType": "String",
123 | "testValue": "\"\""
124 | },
125 | {
126 | "name" : "SignedInteger",
127 | "mangledShorthand" : "SZ",
128 | "testType": "Int",
129 | "testValue": "42"
130 | },
131 | {
132 | "name" : "BinaryInteger",
133 | "mangledShorthand" : "Sz",
134 | "testType": "Int",
135 | "testValue": "42"
136 | },
137 | {
138 | "name" : "Identifiable",
139 | "availability" : "@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)",
140 | "testType": "TestIdentifiable",
141 | "testValue": "TestIdentifiable(id: \"test\")"
142 | }
143 | ]
144 | },
145 | {
146 | "module": "SwiftUI",
147 | "availability" : "@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)",
148 | "types" : [
149 | {
150 | "name" : "View",
151 | "testType": "EmptyView",
152 | "testValue": "EmptyView()"
153 | }
154 | ]
155 | }
156 | ]
157 |
--------------------------------------------------------------------------------
/swift-error-message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nerdsupremacist/AssociatedTypeRequirementsKit/2e4c49c21ffb2135f1c99fbfcf2119c9d24f5e8c/swift-error-message.png
--------------------------------------------------------------------------------
/useGYB:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | find . -name '*.gyb' | \
4 | while read file; do \
5 | gyb --line-directive '' -o "${file%.gyb}" "$file"; \
6 | done
7 |
--------------------------------------------------------------------------------