├── .gitignore ├── LICENSE ├── Package.swift ├── README.md ├── Reflex.podspec ├── Reflex.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── Reflex.xcscheme │ └── ReflexTests.xcscheme ├── Reflex ├── EchoExtensions.swift ├── FLEXSwiftMetadatas.swift ├── FLEXSwiftMirror.swift ├── FLExtensions.swift ├── Info.plist ├── PointerExtensions.swift └── Reflex.h ├── ReflexTests ├── Info.plist ├── ReflexObjcTests.h ├── ReflexObjcTests.mm ├── ReflexTests-Bridging-Header.h ├── ReflexTests.swift └── SampleTypes.swift └── libflex.tbd /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | .DS_Store 20 | /Pods 21 | Podfile.lock 22 | IDEWorkspaceChecks.plist 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2016, Flipboard 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | * Neither the name of Flipboard nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | * You must NOT include this project in an application to be submitted 19 | to the App Store™, as this project uses too many private APIs. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 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: "Reflex", 8 | platforms: [.iOS(.v10)], 9 | products: [ 10 | .library(name: "Reflex", targets: ["Reflex"]), 11 | ], 12 | dependencies: [ 13 | .package(url: "https://github.com/Azoy/Echo", .branch("main")), 14 | .package(url: "https://github.com/FLEXTool/FLEX", .branch("master")), 15 | ], 16 | targets: [ 17 | .target( 18 | name: "Reflex", 19 | dependencies: ["Echo", "FLEX"], 20 | path: "Reflex", 21 | exclude: ["Info.plist"] 22 | ), 23 | .testTarget( 24 | name: "ReflexTests", 25 | dependencies: ["Reflex"], 26 | path: "ReflexTests", 27 | exclude: ["Info.plist"] 28 | ), 29 | ] 30 | ) 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reflex 2 | 3 | A module that adds support for inspecting Swift objects in FLEX. 4 | -------------------------------------------------------------------------------- /Reflex.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'Reflex' 3 | spec.version = '1.0.0' 4 | spec.summary = 'A module that adds support for inspecting Swift objects in FLEX.' 5 | spec.license = { :type => 'BSD', :file => 'LICENSE' } 6 | 7 | spec.author = { 'Tanner Bennett' => 'tannerbennett@me.com' } 8 | spec.homepage = 'https://github.com/FLEXTool/Reflex' 9 | spec.source = { :git => 'https://github.com/FLEXTool/Reflex.git', :tag => '#{spec.version}' } 10 | 11 | spec.dependency 'FLEX', '~> 4.6.0' 12 | 13 | spec.platform = :ios, '12.0' 14 | spec.source_files = 'Reflex/*.swift' 15 | spec.frameworks = [ 'Foundation' ] 16 | spec.swift_version = '5.0' 17 | end 18 | -------------------------------------------------------------------------------- /Reflex.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C30D29862620020B00D89649 /* Reflex.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C30D297C2620020B00D89649 /* Reflex.framework */; }; 11 | C30D298D2620020B00D89649 /* Reflex.h in Headers */ = {isa = PBXBuildFile; fileRef = C30D297F2620020B00D89649 /* Reflex.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | C3442AB02624D62800693972 /* SampleTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3442AAF2624D62800693972 /* SampleTypes.swift */; }; 13 | C3442AC22624D83700693972 /* FLEXSwiftMirror.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3442AC12624D83700693972 /* FLEXSwiftMirror.swift */; }; 14 | C34879E02724F34100815379 /* ReflexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34879DF2724F34100815379 /* ReflexTests.swift */; }; 15 | C34879E92725118000815379 /* EchoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34879E72725118000815379 /* EchoExtensions.swift */; }; 16 | C34879EA2725118000815379 /* PointerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34879E82725118000815379 /* PointerExtensions.swift */; }; 17 | C34879FA2725FE6600815379 /* FLEXSwiftMetadatas.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34879F92725FE6600815379 /* FLEXSwiftMetadatas.swift */; }; 18 | C3570319272BD341002DCB53 /* FLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3570318272BD341002DCB53 /* FLExtensions.swift */; }; 19 | C357BA242819C4B500FFFC96 /* FLEX in Frameworks */ = {isa = PBXBuildFile; productRef = C357BA232819C4B500FFFC96 /* FLEX */; }; 20 | C38D976428192424008709D0 /* libflex.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C3FBA5472741ACE700FBD76E /* libflex.tbd */; }; 21 | C38D976B2819246E008709D0 /* FLEXSwiftMirror.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3442AC12624D83700693972 /* FLEXSwiftMirror.swift */; }; 22 | C38D976C2819246E008709D0 /* FLEXSwiftMetadatas.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34879F92725FE6600815379 /* FLEXSwiftMetadatas.swift */; }; 23 | C38D976D2819246E008709D0 /* EchoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34879E72725118000815379 /* EchoExtensions.swift */; }; 24 | C38D976E2819246E008709D0 /* PointerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34879E82725118000815379 /* PointerExtensions.swift */; }; 25 | C38D976F2819246F008709D0 /* FLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3570318272BD341002DCB53 /* FLExtensions.swift */; }; 26 | C3C30E2A282B63D200AC586A /* Echo in Frameworks */ = {isa = PBXBuildFile; productRef = C3C30E29282B63D200AC586A /* Echo */; }; 27 | C3C30E3A282B64B400AC586A /* Echo in Frameworks */ = {isa = PBXBuildFile; productRef = C3C30E39282B64B400AC586A /* Echo */; }; 28 | C3EA55C826279A7E007611C8 /* ReflexObjcTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = C3EA55C726279A7E007611C8 /* ReflexObjcTests.mm */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXContainerItemProxy section */ 32 | C30D29872620020B00D89649 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = C30D29732620020B00D89649 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = C30D297B2620020B00D89649; 37 | remoteInfo = Reflex; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | C30D297C2620020B00D89649 /* Reflex.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Reflex.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | C30D297F2620020B00D89649 /* Reflex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Reflex.h; sourceTree = ""; }; 44 | C30D29802620020B00D89649 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | C30D29852620020B00D89649 /* ReflexTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReflexTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | C30D298C2620020B00D89649 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | C3442AAF2624D62800693972 /* SampleTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleTypes.swift; sourceTree = ""; }; 48 | C3442AC12624D83700693972 /* FLEXSwiftMirror.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FLEXSwiftMirror.swift; sourceTree = ""; }; 49 | C34879DF2724F34100815379 /* ReflexTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReflexTests.swift; sourceTree = ""; }; 50 | C34879E72725118000815379 /* EchoExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EchoExtensions.swift; sourceTree = ""; }; 51 | C34879E82725118000815379 /* PointerExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PointerExtensions.swift; sourceTree = ""; }; 52 | C34879F92725FE6600815379 /* FLEXSwiftMetadatas.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FLEXSwiftMetadatas.swift; sourceTree = ""; }; 53 | C3570318272BD341002DCB53 /* FLExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FLExtensions.swift; sourceTree = ""; }; 54 | C38D975528192415008709D0 /* libreflex.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libreflex.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | C3EA55C526279A7E007611C8 /* ReflexTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReflexTests-Bridging-Header.h"; sourceTree = ""; }; 56 | C3EA55C626279A7E007611C8 /* ReflexObjcTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReflexObjcTests.h; sourceTree = ""; }; 57 | C3EA55C726279A7E007611C8 /* ReflexObjcTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ReflexObjcTests.mm; sourceTree = ""; }; 58 | C3FBA5472741ACE700FBD76E /* libflex.tbd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.text-based-dylib-definition"; path = libflex.tbd; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | C30D29792620020B00D89649 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | C357BA242819C4B500FFFC96 /* FLEX in Frameworks */, 67 | C3C30E2A282B63D200AC586A /* Echo in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | C30D29822620020B00D89649 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | C30D29862620020B00D89649 /* Reflex.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | C38D975328192415008709D0 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | C38D976428192424008709D0 /* libflex.tbd in Frameworks */, 84 | C3C30E3A282B64B400AC586A /* Echo in Frameworks */, 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | C30D29722620020B00D89649 = { 92 | isa = PBXGroup; 93 | children = ( 94 | C3FBA5472741ACE700FBD76E /* libflex.tbd */, 95 | C30D297E2620020B00D89649 /* Reflex */, 96 | C30D29892620020B00D89649 /* ReflexTests */, 97 | C30D297D2620020B00D89649 /* Products */, 98 | C38D97612819241A008709D0 /* Frameworks */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | C30D297D2620020B00D89649 /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | C30D297C2620020B00D89649 /* Reflex.framework */, 106 | C30D29852620020B00D89649 /* ReflexTests.xctest */, 107 | C38D975528192415008709D0 /* libreflex.dylib */, 108 | ); 109 | name = Products; 110 | sourceTree = ""; 111 | }; 112 | C30D297E2620020B00D89649 /* Reflex */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | C30D29802620020B00D89649 /* Info.plist */, 116 | C30D297F2620020B00D89649 /* Reflex.h */, 117 | C3442AC12624D83700693972 /* FLEXSwiftMirror.swift */, 118 | C34879F92725FE6600815379 /* FLEXSwiftMetadatas.swift */, 119 | C34879E72725118000815379 /* EchoExtensions.swift */, 120 | C34879E82725118000815379 /* PointerExtensions.swift */, 121 | C3570318272BD341002DCB53 /* FLExtensions.swift */, 122 | ); 123 | path = Reflex; 124 | sourceTree = ""; 125 | }; 126 | C30D29892620020B00D89649 /* ReflexTests */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | C30D298C2620020B00D89649 /* Info.plist */, 130 | C3EA55C526279A7E007611C8 /* ReflexTests-Bridging-Header.h */, 131 | C3442AAF2624D62800693972 /* SampleTypes.swift */, 132 | C34879DF2724F34100815379 /* ReflexTests.swift */, 133 | C3EA55C626279A7E007611C8 /* ReflexObjcTests.h */, 134 | C3EA55C726279A7E007611C8 /* ReflexObjcTests.mm */, 135 | ); 136 | path = ReflexTests; 137 | sourceTree = ""; 138 | }; 139 | C38D97612819241A008709D0 /* Frameworks */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | ); 143 | name = Frameworks; 144 | sourceTree = ""; 145 | }; 146 | /* End PBXGroup section */ 147 | 148 | /* Begin PBXHeadersBuildPhase section */ 149 | C30D29772620020B00D89649 /* Headers */ = { 150 | isa = PBXHeadersBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | C30D298D2620020B00D89649 /* Reflex.h in Headers */, 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | C38D975128192415008709D0 /* Headers */ = { 158 | isa = PBXHeadersBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXHeadersBuildPhase section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | C30D297B2620020B00D89649 /* Reflex */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = C30D29902620020B00D89649 /* Build configuration list for PBXNativeTarget "Reflex" */; 170 | buildPhases = ( 171 | C30D29772620020B00D89649 /* Headers */, 172 | C30D29782620020B00D89649 /* Sources */, 173 | C30D29792620020B00D89649 /* Frameworks */, 174 | C30D297A2620020B00D89649 /* Resources */, 175 | ); 176 | buildRules = ( 177 | ); 178 | dependencies = ( 179 | ); 180 | name = Reflex; 181 | packageProductDependencies = ( 182 | C357BA232819C4B500FFFC96 /* FLEX */, 183 | C3C30E29282B63D200AC586A /* Echo */, 184 | ); 185 | productName = Reflex; 186 | productReference = C30D297C2620020B00D89649 /* Reflex.framework */; 187 | productType = "com.apple.product-type.framework"; 188 | }; 189 | C30D29842620020B00D89649 /* ReflexTests */ = { 190 | isa = PBXNativeTarget; 191 | buildConfigurationList = C30D29932620020B00D89649 /* Build configuration list for PBXNativeTarget "ReflexTests" */; 192 | buildPhases = ( 193 | C30D29812620020B00D89649 /* Sources */, 194 | C30D29822620020B00D89649 /* Frameworks */, 195 | C30D29832620020B00D89649 /* Resources */, 196 | ); 197 | buildRules = ( 198 | ); 199 | dependencies = ( 200 | C30D29882620020B00D89649 /* PBXTargetDependency */, 201 | ); 202 | name = ReflexTests; 203 | packageProductDependencies = ( 204 | ); 205 | productName = ReflexTests; 206 | productReference = C30D29852620020B00D89649 /* ReflexTests.xctest */; 207 | productType = "com.apple.product-type.bundle.unit-test"; 208 | }; 209 | C38D975428192415008709D0 /* libreflex */ = { 210 | isa = PBXNativeTarget; 211 | buildConfigurationList = C38D975D28192415008709D0 /* Build configuration list for PBXNativeTarget "libreflex" */; 212 | buildPhases = ( 213 | C38D975128192415008709D0 /* Headers */, 214 | C38D975228192415008709D0 /* Sources */, 215 | C38D975328192415008709D0 /* Frameworks */, 216 | ); 217 | buildRules = ( 218 | ); 219 | dependencies = ( 220 | ); 221 | name = libreflex; 222 | packageProductDependencies = ( 223 | C3C30E39282B64B400AC586A /* Echo */, 224 | ); 225 | productName = libreflex; 226 | productReference = C38D975528192415008709D0 /* libreflex.dylib */; 227 | productType = "com.apple.product-type.library.dynamic"; 228 | }; 229 | /* End PBXNativeTarget section */ 230 | 231 | /* Begin PBXProject section */ 232 | C30D29732620020B00D89649 /* Project object */ = { 233 | isa = PBXProject; 234 | attributes = { 235 | CLASSPREFIX = FLEX; 236 | LastSwiftUpdateCheck = 1240; 237 | LastUpgradeCheck = 1240; 238 | ORGANIZATIONNAME = "Tanner Bennett"; 239 | TargetAttributes = { 240 | C30D297B2620020B00D89649 = { 241 | CreatedOnToolsVersion = 12.4; 242 | LastSwiftMigration = 1240; 243 | }; 244 | C30D29842620020B00D89649 = { 245 | CreatedOnToolsVersion = 12.4; 246 | LastSwiftMigration = 1240; 247 | }; 248 | C38D975428192415008709D0 = { 249 | CreatedOnToolsVersion = 12.4; 250 | }; 251 | }; 252 | }; 253 | buildConfigurationList = C30D29762620020B00D89649 /* Build configuration list for PBXProject "Reflex" */; 254 | compatibilityVersion = "Xcode 9.3"; 255 | developmentRegion = en; 256 | hasScannedForEncodings = 0; 257 | knownRegions = ( 258 | en, 259 | Base, 260 | ); 261 | mainGroup = C30D29722620020B00D89649; 262 | packageReferences = ( 263 | C357BA222819C4B400FFFC96 /* XCRemoteSwiftPackageReference "FLEX" */, 264 | C3C30E28282B63D200AC586A /* XCRemoteSwiftPackageReference "Echo" */, 265 | ); 266 | productRefGroup = C30D297D2620020B00D89649 /* Products */; 267 | projectDirPath = ""; 268 | projectRoot = ""; 269 | targets = ( 270 | C30D297B2620020B00D89649 /* Reflex */, 271 | C30D29842620020B00D89649 /* ReflexTests */, 272 | C38D975428192415008709D0 /* libreflex */, 273 | ); 274 | }; 275 | /* End PBXProject section */ 276 | 277 | /* Begin PBXResourcesBuildPhase section */ 278 | C30D297A2620020B00D89649 /* Resources */ = { 279 | isa = PBXResourcesBuildPhase; 280 | buildActionMask = 2147483647; 281 | files = ( 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | C30D29832620020B00D89649 /* Resources */ = { 286 | isa = PBXResourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | /* End PBXResourcesBuildPhase section */ 293 | 294 | /* Begin PBXSourcesBuildPhase section */ 295 | C30D29782620020B00D89649 /* Sources */ = { 296 | isa = PBXSourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | C34879EA2725118000815379 /* PointerExtensions.swift in Sources */, 300 | C34879E92725118000815379 /* EchoExtensions.swift in Sources */, 301 | C3442AC22624D83700693972 /* FLEXSwiftMirror.swift in Sources */, 302 | C3570319272BD341002DCB53 /* FLExtensions.swift in Sources */, 303 | C34879FA2725FE6600815379 /* FLEXSwiftMetadatas.swift in Sources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | C30D29812620020B00D89649 /* Sources */ = { 308 | isa = PBXSourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | C34879E02724F34100815379 /* ReflexTests.swift in Sources */, 312 | C3EA55C826279A7E007611C8 /* ReflexObjcTests.mm in Sources */, 313 | C3442AB02624D62800693972 /* SampleTypes.swift in Sources */, 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | C38D975228192415008709D0 /* Sources */ = { 318 | isa = PBXSourcesBuildPhase; 319 | buildActionMask = 2147483647; 320 | files = ( 321 | C38D976B2819246E008709D0 /* FLEXSwiftMirror.swift in Sources */, 322 | C38D976C2819246E008709D0 /* FLEXSwiftMetadatas.swift in Sources */, 323 | C38D976D2819246E008709D0 /* EchoExtensions.swift in Sources */, 324 | C38D976E2819246E008709D0 /* PointerExtensions.swift in Sources */, 325 | C38D976F2819246F008709D0 /* FLExtensions.swift in Sources */, 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | /* End PBXSourcesBuildPhase section */ 330 | 331 | /* Begin PBXTargetDependency section */ 332 | C30D29882620020B00D89649 /* PBXTargetDependency */ = { 333 | isa = PBXTargetDependency; 334 | target = C30D297B2620020B00D89649 /* Reflex */; 335 | targetProxy = C30D29872620020B00D89649 /* PBXContainerItemProxy */; 336 | }; 337 | /* End PBXTargetDependency section */ 338 | 339 | /* Begin XCBuildConfiguration section */ 340 | C30D298E2620020B00D89649 /* Debug */ = { 341 | isa = XCBuildConfiguration; 342 | buildSettings = { 343 | ALWAYS_SEARCH_USER_PATHS = NO; 344 | CLANG_ANALYZER_NONNULL = YES; 345 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 346 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 347 | CLANG_CXX_LIBRARY = "libc++"; 348 | CLANG_ENABLE_MODULES = YES; 349 | CLANG_ENABLE_OBJC_ARC = YES; 350 | CLANG_ENABLE_OBJC_WEAK = YES; 351 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 352 | CLANG_WARN_BOOL_CONVERSION = YES; 353 | CLANG_WARN_COMMA = YES; 354 | CLANG_WARN_CONSTANT_CONVERSION = YES; 355 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 356 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 357 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 358 | CLANG_WARN_EMPTY_BODY = YES; 359 | CLANG_WARN_ENUM_CONVERSION = YES; 360 | CLANG_WARN_INFINITE_RECURSION = YES; 361 | CLANG_WARN_INT_CONVERSION = YES; 362 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 363 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 364 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 365 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 366 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 367 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 368 | CLANG_WARN_STRICT_PROTOTYPES = YES; 369 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 370 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 371 | CLANG_WARN_UNREACHABLE_CODE = YES; 372 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 373 | COPY_PHASE_STRIP = NO; 374 | CURRENT_PROJECT_VERSION = 1; 375 | DEBUG_INFORMATION_FORMAT = dwarf; 376 | ENABLE_STRICT_OBJC_MSGSEND = YES; 377 | ENABLE_TESTABILITY = YES; 378 | GCC_C_LANGUAGE_STANDARD = gnu11; 379 | GCC_DYNAMIC_NO_PIC = NO; 380 | GCC_NO_COMMON_BLOCKS = YES; 381 | GCC_OPTIMIZATION_LEVEL = 0; 382 | GCC_PREPROCESSOR_DEFINITIONS = ( 383 | "DEBUG=1", 384 | "$(inherited)", 385 | ); 386 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 387 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 388 | GCC_WARN_UNDECLARED_SELECTOR = YES; 389 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 390 | GCC_WARN_UNUSED_FUNCTION = YES; 391 | GCC_WARN_UNUSED_VARIABLE = YES; 392 | IPHONEOS_DEPLOYMENT_TARGET = 12.2; 393 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 394 | MTL_FAST_MATH = YES; 395 | ONLY_ACTIVE_ARCH = YES; 396 | SDKROOT = iphoneos; 397 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 398 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 399 | VERSIONING_SYSTEM = "apple-generic"; 400 | VERSION_INFO_PREFIX = ""; 401 | }; 402 | name = Debug; 403 | }; 404 | C30D298F2620020B00D89649 /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | ALWAYS_SEARCH_USER_PATHS = NO; 408 | CLANG_ANALYZER_NONNULL = YES; 409 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 410 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 411 | CLANG_CXX_LIBRARY = "libc++"; 412 | CLANG_ENABLE_MODULES = YES; 413 | CLANG_ENABLE_OBJC_ARC = YES; 414 | CLANG_ENABLE_OBJC_WEAK = YES; 415 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_COMMA = YES; 418 | CLANG_WARN_CONSTANT_CONVERSION = YES; 419 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 420 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 421 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 422 | CLANG_WARN_EMPTY_BODY = YES; 423 | CLANG_WARN_ENUM_CONVERSION = YES; 424 | CLANG_WARN_INFINITE_RECURSION = YES; 425 | CLANG_WARN_INT_CONVERSION = YES; 426 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 427 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 428 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 430 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 431 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 432 | CLANG_WARN_STRICT_PROTOTYPES = YES; 433 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 434 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 435 | CLANG_WARN_UNREACHABLE_CODE = YES; 436 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 437 | COPY_PHASE_STRIP = NO; 438 | CURRENT_PROJECT_VERSION = 1; 439 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 440 | ENABLE_NS_ASSERTIONS = NO; 441 | ENABLE_STRICT_OBJC_MSGSEND = YES; 442 | GCC_C_LANGUAGE_STANDARD = gnu11; 443 | GCC_NO_COMMON_BLOCKS = YES; 444 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 445 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 446 | GCC_WARN_UNDECLARED_SELECTOR = YES; 447 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 448 | GCC_WARN_UNUSED_FUNCTION = YES; 449 | GCC_WARN_UNUSED_VARIABLE = YES; 450 | IPHONEOS_DEPLOYMENT_TARGET = 12.2; 451 | MTL_ENABLE_DEBUG_INFO = NO; 452 | MTL_FAST_MATH = YES; 453 | SDKROOT = iphoneos; 454 | SWIFT_COMPILATION_MODE = wholemodule; 455 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 456 | VALIDATE_PRODUCT = YES; 457 | VERSIONING_SYSTEM = "apple-generic"; 458 | VERSION_INFO_PREFIX = ""; 459 | }; 460 | name = Release; 461 | }; 462 | C30D29912620020B00D89649 /* Debug */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | CLANG_ENABLE_MODULES = YES; 466 | CODE_SIGN_STYLE = Automatic; 467 | DEFINES_MODULE = YES; 468 | DEVELOPMENT_TEAM = S6N2F22V2Z; 469 | DYLIB_COMPATIBILITY_VERSION = 1; 470 | DYLIB_CURRENT_VERSION = 1; 471 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 472 | HEADER_SEARCH_PATHS = ( 473 | /opt/theos/vendor/include, 474 | /opt/theos/vendor/include/libflex, 475 | ); 476 | INFOPLIST_FILE = Reflex/Info.plist; 477 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 478 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 479 | LD_RUNPATH_SEARCH_PATHS = ( 480 | "$(inherited)", 481 | "@executable_path/Frameworks", 482 | "@loader_path/Frameworks", 483 | ); 484 | LIBRARY_SEARCH_PATHS = ( 485 | "$(inherited)", 486 | "$(PROJECT_DIR)", 487 | ); 488 | PRODUCT_BUNDLE_IDENTIFIER = com.flextool.Reflex; 489 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 490 | SKIP_INSTALL = YES; 491 | SUPPORTS_MACCATALYST = NO; 492 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 493 | SWIFT_VERSION = 5.0; 494 | TARGETED_DEVICE_FAMILY = "1,2"; 495 | }; 496 | name = Debug; 497 | }; 498 | C30D29922620020B00D89649 /* Release */ = { 499 | isa = XCBuildConfiguration; 500 | buildSettings = { 501 | CLANG_ENABLE_MODULES = YES; 502 | CODE_SIGN_STYLE = Automatic; 503 | DEFINES_MODULE = YES; 504 | DEVELOPMENT_TEAM = S6N2F22V2Z; 505 | DYLIB_COMPATIBILITY_VERSION = 1; 506 | DYLIB_CURRENT_VERSION = 1; 507 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 508 | HEADER_SEARCH_PATHS = ( 509 | /opt/theos/vendor/include, 510 | /opt/theos/vendor/include/libflex, 511 | ); 512 | INFOPLIST_FILE = Reflex/Info.plist; 513 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 514 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 515 | LD_RUNPATH_SEARCH_PATHS = ( 516 | "$(inherited)", 517 | "@executable_path/Frameworks", 518 | "@loader_path/Frameworks", 519 | ); 520 | LIBRARY_SEARCH_PATHS = ( 521 | "$(inherited)", 522 | "$(PROJECT_DIR)", 523 | ); 524 | PRODUCT_BUNDLE_IDENTIFIER = com.flextool.Reflex; 525 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 526 | SKIP_INSTALL = YES; 527 | SUPPORTS_MACCATALYST = NO; 528 | SWIFT_VERSION = 5.0; 529 | TARGETED_DEVICE_FAMILY = "1,2"; 530 | }; 531 | name = Release; 532 | }; 533 | C30D29942620020B00D89649 /* Debug */ = { 534 | isa = XCBuildConfiguration; 535 | buildSettings = { 536 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 537 | CLANG_ENABLE_MODULES = YES; 538 | CODE_SIGN_STYLE = Automatic; 539 | DEVELOPMENT_TEAM = S6N2F22V2Z; 540 | INFOPLIST_FILE = ReflexTests/Info.plist; 541 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 542 | LD_RUNPATH_SEARCH_PATHS = ( 543 | "$(inherited)", 544 | "@executable_path/Frameworks", 545 | "@loader_path/Frameworks", 546 | ); 547 | PRODUCT_BUNDLE_IDENTIFIER = com.flextool.ReflexTests; 548 | PRODUCT_NAME = "$(TARGET_NAME)"; 549 | SWIFT_OBJC_BRIDGING_HEADER = "ReflexTests/ReflexTests-Bridging-Header.h"; 550 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 551 | SWIFT_VERSION = 5.0; 552 | TARGETED_DEVICE_FAMILY = "1,2"; 553 | }; 554 | name = Debug; 555 | }; 556 | C30D29952620020B00D89649 /* Release */ = { 557 | isa = XCBuildConfiguration; 558 | buildSettings = { 559 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 560 | CLANG_ENABLE_MODULES = YES; 561 | CODE_SIGN_STYLE = Automatic; 562 | DEVELOPMENT_TEAM = S6N2F22V2Z; 563 | INFOPLIST_FILE = ReflexTests/Info.plist; 564 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 565 | LD_RUNPATH_SEARCH_PATHS = ( 566 | "$(inherited)", 567 | "@executable_path/Frameworks", 568 | "@loader_path/Frameworks", 569 | ); 570 | PRODUCT_BUNDLE_IDENTIFIER = com.flextool.ReflexTests; 571 | PRODUCT_NAME = "$(TARGET_NAME)"; 572 | SWIFT_OBJC_BRIDGING_HEADER = "ReflexTests/ReflexTests-Bridging-Header.h"; 573 | SWIFT_VERSION = 5.0; 574 | TARGETED_DEVICE_FAMILY = "1,2"; 575 | }; 576 | name = Release; 577 | }; 578 | C38D975B28192415008709D0 /* Debug */ = { 579 | isa = XCBuildConfiguration; 580 | buildSettings = { 581 | CODE_SIGN_STYLE = Automatic; 582 | DEVELOPMENT_TEAM = S6N2F22V2Z; 583 | DYLIB_COMPATIBILITY_VERSION = 1; 584 | DYLIB_CURRENT_VERSION = 1; 585 | EXECUTABLE_PREFIX = lib; 586 | HEADER_SEARCH_PATHS = /opt/theos/vendor/include/libflex; 587 | INSTALL_PATH = /Library/MobileSubstrate/DynamicLibraries; 588 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 589 | LIBRARY_SEARCH_PATHS = ( 590 | "$(inherited)", 591 | "$(PROJECT_DIR)", 592 | ); 593 | MACOSX_DEPLOYMENT_TARGET = 10.15; 594 | PRODUCT_NAME = reflex; 595 | SDKROOT = iphoneos; 596 | SKIP_INSTALL = NO; 597 | STRIP_INSTALLED_PRODUCT = NO; 598 | STRIP_SWIFT_SYMBOLS = NO; 599 | SWIFT_VERSION = 5.0; 600 | }; 601 | name = Debug; 602 | }; 603 | C38D975C28192415008709D0 /* Release */ = { 604 | isa = XCBuildConfiguration; 605 | buildSettings = { 606 | CODE_SIGN_STYLE = Automatic; 607 | DEVELOPMENT_TEAM = S6N2F22V2Z; 608 | DYLIB_COMPATIBILITY_VERSION = 1; 609 | DYLIB_CURRENT_VERSION = 1; 610 | EXECUTABLE_PREFIX = lib; 611 | HEADER_SEARCH_PATHS = /opt/theos/vendor/include/libflex; 612 | INSTALL_PATH = /Library/MobileSubstrate/DynamicLibraries; 613 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 614 | LIBRARY_SEARCH_PATHS = ( 615 | "$(inherited)", 616 | "$(PROJECT_DIR)", 617 | ); 618 | MACOSX_DEPLOYMENT_TARGET = 10.15; 619 | PRODUCT_NAME = reflex; 620 | SDKROOT = iphoneos; 621 | SKIP_INSTALL = NO; 622 | STRIP_INSTALLED_PRODUCT = NO; 623 | STRIP_SWIFT_SYMBOLS = NO; 624 | SWIFT_VERSION = 5.0; 625 | }; 626 | name = Release; 627 | }; 628 | /* End XCBuildConfiguration section */ 629 | 630 | /* Begin XCConfigurationList section */ 631 | C30D29762620020B00D89649 /* Build configuration list for PBXProject "Reflex" */ = { 632 | isa = XCConfigurationList; 633 | buildConfigurations = ( 634 | C30D298E2620020B00D89649 /* Debug */, 635 | C30D298F2620020B00D89649 /* Release */, 636 | ); 637 | defaultConfigurationIsVisible = 0; 638 | defaultConfigurationName = Release; 639 | }; 640 | C30D29902620020B00D89649 /* Build configuration list for PBXNativeTarget "Reflex" */ = { 641 | isa = XCConfigurationList; 642 | buildConfigurations = ( 643 | C30D29912620020B00D89649 /* Debug */, 644 | C30D29922620020B00D89649 /* Release */, 645 | ); 646 | defaultConfigurationIsVisible = 0; 647 | defaultConfigurationName = Release; 648 | }; 649 | C30D29932620020B00D89649 /* Build configuration list for PBXNativeTarget "ReflexTests" */ = { 650 | isa = XCConfigurationList; 651 | buildConfigurations = ( 652 | C30D29942620020B00D89649 /* Debug */, 653 | C30D29952620020B00D89649 /* Release */, 654 | ); 655 | defaultConfigurationIsVisible = 0; 656 | defaultConfigurationName = Release; 657 | }; 658 | C38D975D28192415008709D0 /* Build configuration list for PBXNativeTarget "libreflex" */ = { 659 | isa = XCConfigurationList; 660 | buildConfigurations = ( 661 | C38D975B28192415008709D0 /* Debug */, 662 | C38D975C28192415008709D0 /* Release */, 663 | ); 664 | defaultConfigurationIsVisible = 0; 665 | defaultConfigurationName = Release; 666 | }; 667 | /* End XCConfigurationList section */ 668 | 669 | /* Begin XCRemoteSwiftPackageReference section */ 670 | C357BA222819C4B400FFFC96 /* XCRemoteSwiftPackageReference "FLEX" */ = { 671 | isa = XCRemoteSwiftPackageReference; 672 | repositoryURL = "https://github.com/FLEXTool/FLEX.git"; 673 | requirement = { 674 | branch = master; 675 | kind = branch; 676 | }; 677 | }; 678 | C3C30E28282B63D200AC586A /* XCRemoteSwiftPackageReference "Echo" */ = { 679 | isa = XCRemoteSwiftPackageReference; 680 | repositoryURL = "https://github.com/NSExceptional/Echo"; 681 | requirement = { 682 | branch = "patch-1"; 683 | kind = branch; 684 | }; 685 | }; 686 | /* End XCRemoteSwiftPackageReference section */ 687 | 688 | /* Begin XCSwiftPackageProductDependency section */ 689 | C357BA232819C4B500FFFC96 /* FLEX */ = { 690 | isa = XCSwiftPackageProductDependency; 691 | package = C357BA222819C4B400FFFC96 /* XCRemoteSwiftPackageReference "FLEX" */; 692 | productName = FLEX; 693 | }; 694 | C3C30E29282B63D200AC586A /* Echo */ = { 695 | isa = XCSwiftPackageProductDependency; 696 | package = C3C30E28282B63D200AC586A /* XCRemoteSwiftPackageReference "Echo" */; 697 | productName = Echo; 698 | }; 699 | C3C30E39282B64B400AC586A /* Echo */ = { 700 | isa = XCSwiftPackageProductDependency; 701 | package = C3C30E28282B63D200AC586A /* XCRemoteSwiftPackageReference "Echo" */; 702 | productName = Echo; 703 | }; 704 | /* End XCSwiftPackageProductDependency section */ 705 | }; 706 | rootObject = C30D29732620020B00D89649 /* Project object */; 707 | } 708 | -------------------------------------------------------------------------------- /Reflex.xcodeproj/xcshareddata/xcschemes/Reflex.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Reflex.xcodeproj/xcshareddata/xcschemes/ReflexTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Reflex/EchoExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EchoExtensions.swift 3 | // Reflex 4 | // 5 | // Created by Tanner Bennett on 4/12/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Echo 11 | import CEcho 12 | import FLEX 13 | 14 | typealias RawType = UnsafeRawPointer 15 | typealias Field = (name: String, type: Metadata) 16 | 17 | enum ReflexError: Error { 18 | case failedDynamicCast(src: Any.Type, dest: Any.Type) 19 | 20 | var description: String { 21 | switch self { 22 | case .failedDynamicCast(let src, let dest): 23 | return "Dynamic cast from type '\(src)' to '\(dest)' failed" 24 | } 25 | } 26 | } 27 | 28 | /// For some reason, breaking it all out into separate vars like this 29 | /// eliminated a bug where the pointers in the final set were not the 30 | /// same pointers that would appear if you manually reflected a type 31 | extension KnownMetadata.Builtin { 32 | static var supported: Set = Set(_typePtrs) 33 | 34 | private static var _types: [Any.Type] = [ 35 | Int8.self, Int16.self, Int32.self, Int64.self, Int.self, 36 | UInt8.self, UInt16.self, UInt32.self, UInt64.self, UInt.self, 37 | Float32.self, Float64.self, Float.self, Double.self, CGFloat.self, 38 | ] 39 | 40 | private static var _typePtrs: [RawType] { 41 | return self._types.map { ~$0 } 42 | } 43 | 44 | static var typeEncodings: [RawType: FLEXTypeEncoding] = [ 45 | ~Int8.self: .char, 46 | ~Int16.self: .short, 47 | ~Int32.self: .int, 48 | ~Int64.self: .longLong, 49 | ~Int.self: .longLong, 50 | ~UInt8.self: .unsignedChar, 51 | ~UInt16.self: .unsignedShort, 52 | ~UInt32.self: .unsignedInt, 53 | ~UInt64.self: .unsignedLongLong, 54 | ~UInt.self: .unsignedLongLong, 55 | ~Float32.self: .float, 56 | ~Float64.self: .double, 57 | ~CGFloat.self: .double, 58 | ] 59 | } 60 | 61 | extension KnownMetadata { 62 | static let string: StructDescriptor = reflectStruct(String.self)!.descriptor 63 | static let array: StructDescriptor = reflectStruct([Any].self)!.descriptor 64 | static let dictionary: StructDescriptor = reflectStruct([String:Any].self)!.descriptor 65 | static let date: StructDescriptor = reflectStruct(Date.self)!.descriptor 66 | static let data: StructDescriptor = reflectStruct(Data.self)!.descriptor 67 | static let url: StructDescriptor = reflectStruct(URL.self)!.descriptor 68 | 69 | static let foundationStructs: Set = Set([ 70 | string, array, dictionary, date, data, url 71 | ].map(\.ptr)) 72 | 73 | static func isFoundationStruct(_ metadata: Metadata) -> Bool { 74 | guard let metadata = metadata as? StructMetadata else { 75 | return false 76 | } 77 | 78 | return foundationStructs.contains(metadata.descriptor.ptr) 79 | } 80 | 81 | static let foundationTypeDescriptorToClass: [RawType: AnyClass] = [ 82 | string.ptr: NSString.self, 83 | array.ptr: NSArray.self, 84 | dictionary.ptr: NSDictionary.self, 85 | date.ptr: NSDate.self, 86 | data.ptr: NSData.self, 87 | url.ptr: NSURL.self, 88 | ] 89 | 90 | static func classForStruct(_ metadata: Metadata) -> AnyClass? { 91 | guard let metadata = metadata as? StructMetadata else { 92 | return nil 93 | } 94 | 95 | return foundationTypeDescriptorToClass[metadata.descriptor.ptr] 96 | } 97 | } 98 | 99 | extension Metadata { 100 | private var `enum`: EnumMetadata { self as! EnumMetadata } 101 | private var `struct`: StructMetadata { self as! StructMetadata } 102 | private var tuple: TupleMetadata { self as! TupleMetadata } 103 | 104 | /// This doesn't actually work very well since Double etc aren't opaque, 105 | /// but instead contain a single member that is itself opaque 106 | private var isBuiltin_alt: Bool { 107 | return self is OpaqueMetadata 108 | } 109 | 110 | /// This is `true` for any "primitive" type 111 | var isBuiltin: Bool { 112 | guard self.vwt.flags.isPOD else { 113 | return false 114 | } 115 | 116 | return KnownMetadata.Builtin.supported.contains(self.ptr) 117 | } 118 | 119 | /// Whether this type represents a struct (or optional) besides 120 | /// a primitive that is bridged to Objective-C as an object 121 | var isNonTriviallyBridgedToObjc: Bool { 122 | switch self.kind { 123 | case .struct: 124 | return KnownMetadata.isFoundationStruct(self.struct) 125 | case .optional: 126 | return self.enum.optionalType.isNonTriviallyBridgedToObjc 127 | 128 | default: 129 | return false 130 | } 131 | } 132 | 133 | /// Programmatically perform a cast like `foo as? T` at runtime 134 | func dynamicCast(from variable: Any) throws -> Any { 135 | func cast(_: T.Type) throws -> T { 136 | guard let casted = variable as? T else { 137 | let srcType = Swift.type(of: variable) 138 | throw ReflexError.failedDynamicCast(src: srcType, dest: T.self) 139 | } 140 | 141 | return casted 142 | } 143 | 144 | return try _openExistential(self.type, do: cast(_:)) 145 | } 146 | 147 | var typeEncoding: FLEXTypeEncoding { 148 | switch self.kind { 149 | case .class: 150 | return .objcObject 151 | 152 | case .struct: 153 | // Hard-code types for builtin types and a few foundation structs 154 | if self.isBuiltin { 155 | return KnownMetadata.Builtin.typeEncodings[~self.type]! 156 | } 157 | // If it bridges to Objc and _isn't_ a primitive, treat it as an object 158 | if self.isNonTriviallyBridgedToObjc { 159 | // TODO encode as proper type 160 | return .objcObject 161 | } 162 | 163 | return .structBegin 164 | 165 | case .enum: 166 | if self.enum.descriptor.numPayloadCases > 0 { 167 | return .unknown 168 | } 169 | return .unknown // TODO: return proper sized int for enums? 170 | 171 | case .optional: 172 | // For optionals, use the encoding of the Wrapped type 173 | return self.enum.optionalType!.typeEncoding 174 | 175 | case .tuple: 176 | return .structBegin 177 | 178 | case .foreignClass, 179 | .opaque, 180 | .function, 181 | .existential, 182 | .metatype, 183 | .objcClassWrapper, 184 | .existentialMetatype, 185 | .heapLocalVariable, 186 | .heapGenericLocalVariable, 187 | .errorObject: 188 | return .unknown 189 | } 190 | } 191 | 192 | // TODO: enums would show up as anonymous structs I think 193 | var typeEncodingString: String { 194 | switch self.typeEncoding { 195 | case .objcObject: 196 | return FLEXTypeEncoding.encodeObjcObject(typeName: self.description) 197 | case .structBegin: 198 | switch self.kind { 199 | case .tuple: 200 | let fieldTypes = self.tuple.elements.map(\.metadata.typeEncodingString) 201 | return FLEXTypeEncoding.encodeStruct(typeName: self.description, fields: fieldTypes) 202 | case .struct: 203 | let fieldTypes = self.struct.fields.map(\.type.typeEncodingString) 204 | return FLEXTypeEncoding.encodeStruct(typeName: self.description, fields: fieldTypes) 205 | case .optional: 206 | return self.enum.optionalType!.typeEncodingString 207 | default: 208 | fatalError() 209 | } 210 | default: 211 | // For now, convert type encoding char into a string 212 | return String(Character(.init(UInt8(bitPattern: self.typeEncoding.rawValue)))) 213 | } 214 | } 215 | } 216 | 217 | protocol NominalType: TypeMetadata { 218 | var genericMetadata: [Metadata] { get } 219 | var fieldOffsets: [Int] { get } 220 | var fields: [Field] { get } 221 | var description: String { get } 222 | } 223 | 224 | protocol ContextualNominalType: NominalType { 225 | associatedtype NominalTypeDescriptor: TypeContextDescriptor 226 | var descriptor: NominalTypeDescriptor { get } 227 | } 228 | 229 | extension ClassMetadata: NominalType, ContextualNominalType { 230 | typealias NominalTypeDescriptor = ClassDescriptor 231 | } 232 | extension StructMetadata: NominalType, ContextualNominalType { 233 | typealias NominalTypeDescriptor = StructDescriptor 234 | } 235 | extension EnumMetadata: NominalType, ContextualNominalType { 236 | typealias NominalTypeDescriptor = EnumDescriptor 237 | } 238 | 239 | // MARK: KVC 240 | extension ContextualNominalType { 241 | func recordIndex(forKey key: String) -> Int? { 242 | return self.descriptor.fields.records.firstIndex { $0.name == key } 243 | } 244 | 245 | func fieldOffset(for key: String) -> Int? { 246 | if let idx = self.recordIndex(forKey: key) { 247 | return self.fieldOffsets[idx] 248 | } 249 | 250 | return nil 251 | } 252 | 253 | func fieldType(for key: String) -> Metadata? { 254 | return self.fields.first(where: { $0.name == key })?.type 255 | } 256 | 257 | var shallowFields: [Field] { 258 | let r: [FieldRecord] = self.descriptor.fields.records 259 | return r.filter(\.hasMangledTypeName).map { 260 | return ( 261 | $0.name, 262 | reflect(self.type(of: $0.mangledTypeName)!) 263 | ) 264 | } 265 | } 266 | } 267 | 268 | extension StructMetadata { 269 | func getValue(forKey key: String, from object: O) -> T { 270 | let offset = self.fieldOffset(for: key)! 271 | let ptr = object~ 272 | return ptr[offset] 273 | } 274 | 275 | func getValueBox(forKey key: String, from object: O) -> AnyExistentialContainer { 276 | guard let offset = self.fieldOffset(for: key), let type = self.fieldType(for: key) else { 277 | fatalError("Class '\(self.descriptor.name)' has no member '\(key)'") 278 | } 279 | 280 | let ptr = object~ 281 | return .init(boxing: ptr + offset, type: type) 282 | } 283 | 284 | func set(value: T, forKey key: String, on object: inout O) { 285 | self.set(value: value, forKey: key, pointer: object~) 286 | } 287 | 288 | func set(value: Any, forKey key: String, pointer ptr: RawPointer) { 289 | let offset = self.fieldOffset(for: key)! 290 | let type = self.fieldType(for: key)! 291 | ptr.storeBytes(of: value, type: type, offset: offset) 292 | } 293 | 294 | var fields: [Field] { self.shallowFields } 295 | } 296 | 297 | extension ClassMetadata { 298 | /// Does not traverse the class hierarchy 299 | private func objcIvar(for key: String) -> Ivar? { 300 | guard let idx = self.descriptor.fields.records.map(\.name) 301 | .firstIndex(where: { $0 == key }) else { 302 | return nil 303 | } 304 | 305 | var count: UInt32 = 0 306 | guard let ivars = class_copyIvarList(self.type as? AnyClass, &count) else { 307 | return nil 308 | } 309 | 310 | defer { free(ivars) } 311 | return ivars[idx] 312 | } 313 | 314 | /// Does not traverse the class hierarchy 315 | func ivarOffset(for key: String) -> Int? { 316 | // If the class has objc heritage, get the field offset using the objc 317 | // metadata, because Swift won't update the field offsets in the face of 318 | // resilient base classes 319 | guard self.flags.usesSwiftRefCounting else { 320 | guard let ivar = self.objcIvar(for: key) else { 321 | return nil 322 | } 323 | 324 | return ivar_getOffset(ivar) 325 | } 326 | 327 | // Does this ivar exist? 328 | guard let idx = self.recordIndex(forKey: key) else { 329 | // Not here, but maybe in a superclass 330 | return nil 331 | } 332 | 333 | // Yes! Now, grab the offset and offset it by the superclass's instance size 334 | // if let supercls = self.superclassMetadata?.type { 335 | // return self.fieldOffsets[idx] //+ class_getInstanceSize(supercls as? AnyClass) 336 | // } 337 | 338 | return self.fieldOffsets[idx] 339 | } 340 | 341 | func getValue(forKey key: String, from object: O) -> T { 342 | guard let offset = self.ivarOffset(for: key) else { 343 | if let sup = self.superclassMetadata { 344 | return sup.getValue(forKey: key, from: object) 345 | } else { 346 | fatalError("Class '\(self.descriptor.name)' has no member '\(key)'") 347 | } 348 | } 349 | 350 | let ptr = object~ 351 | return ptr[offset] 352 | } 353 | 354 | func getValueBox(forKey key: String, from object: O) -> AnyExistentialContainer { 355 | guard let offset = self.ivarOffset(for: key), let type = self.fieldType(for: key) else { 356 | if let sup = self.superclassMetadata { 357 | return sup.getValueBox(forKey: key, from: object) 358 | } else { 359 | fatalError("Class '\(self.descriptor.name)' has no member '\(key)'") 360 | } 361 | } 362 | 363 | let ptr = object~ 364 | return .init(boxing: ptr + offset, type: type) 365 | } 366 | 367 | func set(value: T, forKey key: String, on object: inout O) { 368 | self.set(value: value, forKey: key, pointer: object~) 369 | } 370 | 371 | func set(value: Any, forKey key: String, pointer ptr: RawPointer) { 372 | guard let offset = self.ivarOffset(for: key) else { 373 | if let sup = self.superclassMetadata { 374 | return sup.set(value: value, forKey: key, pointer: ptr) 375 | } else { 376 | fatalError("Class '\(self.descriptor.name)' has no member '\(key)'") 377 | } 378 | } 379 | 380 | var value = value 381 | let box = container(for: value) 382 | 383 | // Check if we need to do a cast first; sometimes things like 384 | // Double or Int will be boxed up as NSNumber first. 385 | let type = self.fieldType(for: key)! 386 | if type.type != box.type, let cast = try? type.dynamicCast(from: value) { 387 | value = cast 388 | } 389 | 390 | ptr.storeBytes(of: value, type: type, offset: offset) 391 | } 392 | 393 | /// Consolidate all fields in the class hierarchy 394 | var fields: [Field] { 395 | if let sup = self.superclassMetadata, sup.isSwiftClass { 396 | return self.shallowFields + sup.fields 397 | } 398 | 399 | return self.shallowFields 400 | } 401 | } 402 | 403 | extension EnumMetadata { 404 | var fields: [Field] { self.shallowFields } 405 | } 406 | 407 | // MARK: Protocol conformance checking 408 | extension TypeMetadata { 409 | func conforms(to _protocol: Any) -> Bool { 410 | let existential = reflect(_protocol) as! MetatypeMetadata 411 | let instance = existential.instanceMetadata as! ExistentialMetadata 412 | let desc = instance.protocols.first! 413 | 414 | return !self.conformances.filter({ $0.protocol == desc }).isEmpty 415 | } 416 | } 417 | 418 | // MARK: MetadataKind 419 | extension MetadataKind { 420 | var isObject: Bool { 421 | return self == .class || self == .objcClassWrapper 422 | } 423 | } 424 | 425 | // MARK: Populating AnyExistentialContainer 426 | extension AnyExistentialContainer { 427 | var toAny: Any { 428 | return unsafeBitCast(self, to: Any.self) 429 | } 430 | 431 | var isEmpty: Bool { 432 | return self.data == (0, 0, 0) 433 | } 434 | 435 | init(boxing valuePtr: RawPointer, type: Metadata) { 436 | self = .init(metadata: type) 437 | self.store(value: valuePtr) 438 | } 439 | 440 | init(nil optionalType: EnumMetadata) { 441 | self = .init(metadata: optionalType) 442 | self.zeroMemory() 443 | } 444 | 445 | init(nil optionalType: ClassMetadata) { 446 | self = .init(metadata: optionalType) 447 | self.zeroMemory() 448 | } 449 | 450 | mutating func store(value newValuePtr: RawPointer) { 451 | self.metadata.vwt.initializeWithCopy(self.getValueBuffer(), newValuePtr) 452 | } 453 | 454 | /// Calls into `projectValue()` but will allocate a box 455 | /// first if needed for types that are not inline 456 | mutating func getValueBuffer() -> RawPointer { 457 | // Allocate a box if needed and return it 458 | if !self.metadata.vwt.flags.isValueInline && self.data.0 == 0 { 459 | return self.metadata.allocateBoxForExistential(in: &self)~ 460 | } 461 | 462 | // We don't need a box or already have one 463 | return self.projectValue()~ 464 | } 465 | 466 | mutating func zeroMemory() { 467 | let size = self.metadata.vwt.size 468 | self.getValueBuffer().initializeMemory( 469 | as: Int8.self, repeating: 0, count: size 470 | ) 471 | } 472 | } 473 | 474 | extension FieldRecord: CustomDebugStringConvertible { 475 | public var debugDescription: String { 476 | let ptr = self.mangledTypeName.assumingMemoryBound(to: UInt8.self) 477 | return self.name + ": \(String(cString: ptr)) ( \(self.referenceStorage) : \(self.flags))" 478 | } 479 | } 480 | 481 | extension EnumMetadata { 482 | fileprivate var optionalType: Metadata! { self.genericMetadata.first } 483 | 484 | func getTag(for instance: Any) -> UInt32 { 485 | var box = container(for: instance) 486 | return self.enumVwt.getEnumTag(for: box.projectValue()) 487 | } 488 | 489 | func copyPayload(from instance: Any) -> (value: Any, type: Any.Type)? { 490 | let tag = self.getTag(for: instance) 491 | let isPayloadCase = self.descriptor.numPayloadCases > tag 492 | if isPayloadCase { 493 | let caseRecord = self.descriptor.fields.records[Int(tag)] 494 | let type = self.type(of: caseRecord.mangledTypeName)! 495 | var caseBox = container(for: instance) 496 | // Copies in the value and allocates a box as needed 497 | let payload = AnyExistentialContainer( 498 | boxing: caseBox.projectValue()~, 499 | type: reflect(type) 500 | ) 501 | return (unsafeBitCast(payload, to: Any.self), type) 502 | } 503 | 504 | return nil 505 | } 506 | } 507 | 508 | extension ProtocolDescriptor { 509 | var description: String { 510 | return self.name 511 | } 512 | } 513 | 514 | extension FunctionMetadata { 515 | var typeSignature: String { 516 | let params = self.paramMetadata.map(\.description).joined(separator: ", ") 517 | return "(" + params + ") -> " + self.resultMetadata.description 518 | } 519 | } 520 | 521 | extension TupleMetadata { 522 | var signature: String { 523 | let pairs = zip(self.labels, self.elements) 524 | return "(" + pairs.map { "\($0): \($1.metadata.description)" }.joined(separator: ", ") + ")" 525 | } 526 | } 527 | 528 | extension NominalType { 529 | var genericDescription: String { 530 | return "\(self.type)" 531 | // let generics = self.genericMetadata.map(\.description).joined(separator: ", ") 532 | // guard !generics.isEmpty else { 533 | // return "\(self.type)" 534 | // } 535 | // 536 | // return "\(self.type)<\(generics)>" 537 | } 538 | } 539 | 540 | extension Metadata { 541 | var description: String { 542 | switch self.kind { 543 | case .class, .struct, .enum: 544 | return "\((self as! NominalType).genericDescription)" 545 | case .optional: 546 | return "\(self.enum.optionalType!.description)?" 547 | case .foreignClass: 548 | return "~ForeignClass" 549 | case .opaque: 550 | return "~Opaque" 551 | case .tuple: 552 | return (self as! TupleMetadata).signature 553 | case .function: 554 | return (self as! FunctionMetadata).typeSignature 555 | case .existential: 556 | if self.ptr~ == Any.self~ || self.ptr~ == AnyObject.self~ { 557 | return "\(self.type)" 558 | } 559 | 560 | let ext = (self as! ExistentialMetadata) 561 | let protocols = ext.protocols.map(\.description).joined(separator: " & ") 562 | if let supercls = ext.superclassMetadata { 563 | return supercls.description + " & " + protocols 564 | } else { 565 | return protocols 566 | } 567 | case .metatype: 568 | return (self as! MetatypeMetadata).instanceMetadata.description + ".self" 569 | case .objcClassWrapper: 570 | return "~ObjcClassWrapper" 571 | case .existentialMetatype: 572 | if self.ptr~ == AnyClass.self~ { 573 | return "AnyClass" 574 | } 575 | return "~Existential" 576 | case .heapLocalVariable: 577 | return "~HLV" 578 | case .heapGenericLocalVariable: 579 | return "~HGLV" 580 | case .errorObject: 581 | return "~ErrorObject" 582 | } 583 | } 584 | } 585 | -------------------------------------------------------------------------------- /Reflex/FLEXSwiftMetadatas.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FLEXSwiftMetadatas.swift 3 | // Reflex 4 | // 5 | // Created by Tanner Bennett on 10/24/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | import FLEX 10 | import Echo 11 | 12 | extension SwiftMirror { 13 | static func imagePath(for pointer: UnsafeRawPointer) -> String? { 14 | var exeInfo = Dl_info() 15 | if (dladdr(pointer, &exeInfo) != 0) { 16 | if let fname = exeInfo.dli_fname { 17 | return String(cString: fname) 18 | } 19 | } 20 | 21 | return nil 22 | } 23 | } 24 | 25 | @objc(FLEXSwiftIvar) 26 | public class SwiftIvar: FLEXIvar { 27 | 28 | convenience init(field: Field, class: ClassMetadata) { 29 | self.init( 30 | field: field, 31 | offset: `class`.fieldOffset(for: field.name)!, 32 | parent: `class` 33 | ) 34 | } 35 | 36 | init(field: Field, offset: Int, parent: Metadata) { 37 | self.property = field 38 | self._offset = offset 39 | self._imagePath = SwiftMirror.imagePath(for: parent.ptr) 40 | } 41 | 42 | public override var name: String { self.property.name } 43 | public override var type: FLEXTypeEncoding { _typeChar } 44 | public override var typeEncoding: String { _typeEncodingString } 45 | public override var offset: Int { _offset } 46 | public override var size: UInt { UInt(self.property.type.vwt.size) } 47 | public override var imagePath: String? { self._imagePath } 48 | 49 | private let property: Field 50 | private let _offset: Int 51 | private let _imagePath: String? 52 | 53 | private lazy var _typeChar = self.property.type.typeEncoding 54 | private lazy var _typeEncodingString = self.property.type.typeEncodingString 55 | 56 | public override var details: String { 57 | "\(size) bytes, \(offset), \(typeEncoding)" 58 | } 59 | 60 | public override func description() -> String! { 61 | if self.type == .structBegin, let structMetadata = self.property.type as? StructMetadata { 62 | return "\(structMetadata.description) \(self.name)" 63 | } 64 | 65 | let desc = super.description() 66 | // Make things like `String *foo` appear as `String foo` 67 | if self.property.type.isNonTriviallyBridgedToObjc { 68 | return desc?.replacingOccurrences(of: " *", with: " ") 69 | } 70 | 71 | return desc 72 | } 73 | 74 | public override func getValue(_ target: Any) -> Any? { 75 | // Target must be AnyObject for KVC to work 76 | let target = target as AnyObject 77 | let type = reflect(target) as! ClassMetadata 78 | 79 | return type.getValueBox(forKey: self.name, from: target).toAny 80 | } 81 | 82 | public override func setValue(_ value: Any?, on target: Any) { 83 | // Target must be AnyObject for KVC to work 84 | let target = target as AnyObject 85 | let type = reflect(target) as! ClassMetadata 86 | 87 | if let value = value { 88 | // Not nil, nothing to do here 89 | type.set(value: value, forKey: self.name, pointer: target~) 90 | } else { 91 | // Value was nil; only supported on optional types or class types 92 | let kind = self.property.type.kind 93 | let nilValue: Any 94 | 95 | switch kind { 96 | case .enum: 97 | nilValue = AnyExistentialContainer(nil: self.property.type as! EnumMetadata) 98 | case .class: 99 | nilValue = AnyExistentialContainer(nil: self.property.type as! ClassMetadata) 100 | default: 101 | fatalError("Attempting to set nil to non-optional property") 102 | } 103 | 104 | type.set(value: nilValue, forKey: self.name, pointer: target~) 105 | } 106 | 107 | } 108 | 109 | public override func getPotentiallyUnboxedValue(_ target: Any) -> Any? { 110 | return self.getValue(target) 111 | } 112 | 113 | public override func auxiliaryInfo(forKey key: String) -> Any? { 114 | switch key { 115 | case FLEXAuxiliarynfoKeyFieldLabels: 116 | return self.structFieldNamesDict(from: self.property.type.struct) 117 | default: 118 | return nil 119 | } 120 | } 121 | 122 | private func structFieldNamesDict(from metadata: StructMetadata?) -> [String: [String]] { 123 | guard let metadata = metadata else { return [:] } 124 | 125 | func typeAndLabels(from metadata: StructMetadata) -> (String, [String]) { 126 | let key = metadata.typeEncodingString 127 | let labels = metadata.fields.map { "\($0.type.description) \($0.name)" } 128 | return (key, labels) 129 | } 130 | 131 | let topLevel = typeAndLabels(from: metadata) 132 | var mapping = [topLevel.0: topLevel.1] 133 | 134 | let childTypes = metadata.fields 135 | .compactMap { $0.type.struct } 136 | .map { typeAndLabels(from: $0) } 137 | 138 | for (key, labels) in childTypes { 139 | mapping[key] = labels 140 | } 141 | 142 | return mapping 143 | } 144 | } 145 | 146 | fileprivate extension Metadata { 147 | var `struct`: StructMetadata? { self as? StructMetadata } 148 | } 149 | 150 | @objc(FLEXSwiftProtocol) 151 | public class SwiftProtocol: FLEXProtocol { 152 | private let `protocol`: ProtocolDescriptor 153 | 154 | init(protocol ptcl: ProtocolDescriptor) { 155 | self.protocol = ptcl 156 | 157 | super.init() 158 | } 159 | 160 | public override var name: String { 161 | return self.protocol.name 162 | } 163 | 164 | public override var objc_protocol: Protocol { 165 | // Swift protocol requirements have no names (to my knowledge) 166 | // and a Swift protocol is not an objc object, so returning 167 | // this protocol is the best we can do, and has no drawbacks 168 | return NSObjectProtocol.self 169 | } 170 | 171 | private lazy var _imagePath: String? = { 172 | var exeInfo: Dl_info! = nil 173 | if (dladdr(self.protocol.ptr, &exeInfo) != 0) { 174 | if let fname = exeInfo.dli_fname { 175 | return String(cString: fname) 176 | } 177 | } 178 | 179 | return nil 180 | }() 181 | 182 | private lazy var swiftProtocols: [ProtocolDescriptor] = [] 183 | 184 | public override var imagePath: String? { self._imagePath } 185 | 186 | public override var protocols: [FLEXProtocol] { self.swiftProtocols.map(SwiftProtocol.init(protocol:)) } 187 | public override var requiredMethods: [FLEXMethodDescription] { [] } 188 | public override var optionalMethods: [FLEXMethodDescription] { [] } 189 | 190 | public override var requiredProperties: [FLEXProperty] { [] } 191 | public override var optionalProperties: [FLEXProperty] { [] } 192 | } 193 | -------------------------------------------------------------------------------- /Reflex/FLEXSwiftMirror.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FLEXSwiftMirror.swift 3 | // Reflex 4 | // 5 | // Created by Tanner Bennett on 4/12/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import FLEX 11 | import Echo 12 | 13 | @objc(FLEXSwiftMirror) 14 | public class SwiftMirror: NSObject, FLEXMirrorProtocol { 15 | 16 | /// Never a metaclass 17 | private let `class`: AnyClass 18 | private let metadata: ClassMetadata 19 | private var flexMirror: FLEXMirror { 20 | .init(reflecting: self.value) 21 | } 22 | 23 | /// Really it's AnyObject 24 | public let value: Any 25 | public let isClass: Bool 26 | public let className: String 27 | 28 | private(set) public var properties: [FLEXProperty] = [] 29 | private(set) public var classProperties: [FLEXProperty] = [] 30 | private(set) public var ivars: [FLEXIvar] = [] 31 | private(set) public var methods: [FLEXMethod] = [] 32 | private(set) public var classMethods: [FLEXMethod] = [] 33 | private(set) public var protocols: [FLEXProtocol] = [] 34 | 35 | public var superMirror: FLEXMirrorProtocol? { 36 | guard let supercls = class_getSuperclass(self.class) else { 37 | return nil 38 | } 39 | 40 | if reflectClass(supercls)!.isSwiftClass { 41 | return Self.init(reflecting: supercls) 42 | } else { 43 | return FLEXMirror(reflecting: supercls) 44 | } 45 | } 46 | 47 | required public init(reflecting objectOrClass: Any) { 48 | let cls: AnyClass = object_getClass(objectOrClass)! 49 | 50 | self.value = objectOrClass 51 | self.isClass = class_isMetaClass(cls) 52 | self.className = NSStringFromClass(cls) 53 | 54 | self.class = self.isClass ? objectOrClass as! AnyClass : cls 55 | self.metadata = reflectClass(self.class)! 56 | 57 | super.init() 58 | self.examine() 59 | } 60 | 61 | private func examine() { 62 | let swiftIvars: [SwiftIvar] = self.metadata.shallowFields.map { 63 | .init(field: $0, class: self.metadata) 64 | } 65 | 66 | let swiftProtos: [SwiftProtocol] = self.metadata.conformances 67 | .map(\.protocol) 68 | .map { .init(protocol: $0) } 69 | 70 | let fm = self.flexMirror 71 | let ivarNames = Set(swiftIvars.map(\.name)) 72 | self.ivars = swiftIvars + fm.ivars.filter { !ivarNames.contains($0.name) } 73 | self.protocols = swiftProtos + fm.protocols 74 | 75 | self.properties = fm.properties 76 | self.classProperties = fm.classProperties 77 | self.methods = fm.methods 78 | self.classMethods = fm.classMethods 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Reflex/FLExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FLExtensions.swift 3 | // Reflex 4 | // 5 | // Created by Tanner Bennett on 10/29/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | import FLEX 10 | 11 | extension FLEXTypeEncoding { 12 | static func encodeObjcObject(typeName: String) -> String { 13 | return "@\"\(typeName)\"" 14 | } 15 | 16 | static func encodeStruct(typeName: String? = nil, fields: [String]) -> String { 17 | if let typeName = typeName { 18 | return "{\(typeName)=\(fields.joined())}" 19 | } 20 | 21 | return "{\(fields.joined())}" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Reflex/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /Reflex/PointerExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // ReflexTests 4 | // 5 | // Created by Tanner Bennett on 4/12/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Echo 11 | 12 | typealias RawPointer = UnsafeMutableRawPointer 13 | 14 | extension UnsafeRawPointer { 15 | subscript(offset: Int) -> T { 16 | get { 17 | return self.load(fromByteOffset: offset, as: T.self) 18 | } 19 | } 20 | } 21 | 22 | extension RawPointer { 23 | /// Generic subscript. Do not use when T = Any unless you mean it... 24 | subscript(offset: Int) -> T { 25 | get { 26 | return self.load(fromByteOffset: offset, as: T.self) 27 | } 28 | 29 | set { 30 | self.storeBytes(of: newValue, toByteOffset: offset, as: T.self) 31 | } 32 | } 33 | 34 | /// Allocates space for a structure (or enum?) without an initial value 35 | static func allocateBuffer(for type: Metadata) -> Self { 36 | return RawPointer.allocate( 37 | byteCount: type.vwt.size, 38 | alignment: type.vwt.flags.alignment 39 | ) 40 | } 41 | 42 | /// Allocates space for and stores a value. 43 | /// You should probably use AnyExistentialContainer instead. 44 | init(wrapping value: Any, withType metadata: Metadata) { 45 | self = RawPointer.allocateBuffer(for: metadata) 46 | self.storeBytes(of: value, type: metadata) 47 | } 48 | 49 | /// For storing a value from an Any container 50 | func storeBytes(of value: Any, type: Metadata, offset: Int = 0) { 51 | var box = container(for: value) 52 | type.vwt.initializeWithCopy((self + offset), box.projectValue()~) 53 | // (self + offset).copyMemory(from: box.projectValue(), byteCount: type.vwt.size) 54 | } 55 | 56 | /// For copying a tuple element instance from a pointer 57 | func copyMemory(ofTupleElement valuePtr: UnsafeRawPointer, layout e: TupleMetadata.Element) { 58 | e.metadata.vwt.initializeWithCopy((self + e.offset), valuePtr~) 59 | // (self + e.offset).copyMemory(from: valuePtr, byteCount: e.metadata.vwt.size) 60 | } 61 | 62 | /// For copying a type instance from a pointer 63 | func copyMemory(from pointer: RawPointer, type: Metadata, offset: Int = 0) { 64 | type.vwt.initializeWithCopy((self + offset), pointer) 65 | // (self + offset).copyMemory(from: pointer, byteCount: type.vwt.size) 66 | } 67 | } 68 | 69 | extension Unmanaged where Instance == AnyObject { 70 | /// Quickly retain an object before you write its address to memory or something 71 | @discardableResult 72 | static func retainIfObject(_ thing: Any) -> Bool { 73 | if container(for: thing).metadata.kind.isObject { 74 | _ = self.passRetained(thing as AnyObject).retain() 75 | return true 76 | } 77 | 78 | return false 79 | } 80 | } 81 | 82 | postfix operator ~ 83 | postfix func ~(target: T) -> RawPointer { 84 | return unsafeBitCast(target, to: RawPointer.self) 85 | } 86 | prefix func ~(target: T) -> U { 87 | return unsafeBitCast(target, to: U.self) 88 | } 89 | -------------------------------------------------------------------------------- /Reflex/Reflex.h: -------------------------------------------------------------------------------- 1 | // 2 | // Reflex.h 3 | // Reflex 4 | // 5 | // Created by Tanner Bennett on 4/8/21. 6 | // 7 | 8 | #import 9 | @import FLEX; 10 | -------------------------------------------------------------------------------- /ReflexTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ReflexTests/ReflexObjcTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReflexObjcTests.h 3 | // ReflexTests 4 | // 5 | // Created by Tanner Bennett on 4/14/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | BOOL isSwiftObjectOrClass(id objOrClass); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | 24 | @interface RFView : NSObject 25 | 26 | - (id)initWithColor:(UIColor *)color frame:(CGRect)frame; 27 | 28 | @property (nonatomic, readonly) CGRect frame; 29 | @property (nonatomic, readonly) UIColor *color; 30 | @property (nonatomic, readonly) BOOL hidden; 31 | @property (nonatomic, readonly) CGFloat alpha; 32 | 33 | - (void)layoutSubviews; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | 39 | -------------------------------------------------------------------------------- /ReflexTests/ReflexObjcTests.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ReflexObjcTests.m 3 | // ReflexTests 4 | // 5 | // Created by Tanner Bennett on 4/14/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | #import "ReflexObjcTests.h" 10 | #import 11 | #include 12 | 13 | // class is a Swift class from the pre-stable Swift ABI 14 | #define FAST_IS_SWIFT_LEGACY (1UL<<0) 15 | // class is a Swift class from the stable Swift ABI 16 | #define FAST_IS_SWIFT_STABLE (1UL<<1) 17 | // data pointer 18 | #define FAST_DATA_MASK 0xfffffffcUL 19 | 20 | typedef uintptr_t class_data_bits_t; 21 | #if __LP64__ 22 | typedef uint32_t mask_t; // x86_64 & arm64 asm are less efficient with 16-bits 23 | #else 24 | typedef uint16_t mask_t; 25 | #endif 26 | 27 | /* dyld_shared_cache_builder and obj-C agree on these definitions */ 28 | struct preopt_cache_entry_t { 29 | uint32_t sel_offs; 30 | uint32_t imp_offs; 31 | }; 32 | 33 | /* dyld_shared_cache_builder and obj-C agree on these definitions */ 34 | struct preopt_cache_t { 35 | int32_t fallback_class_offset; 36 | union { 37 | struct { 38 | uint16_t shift : 5; 39 | uint16_t mask : 11; 40 | }; 41 | uint16_t hash_params; 42 | }; 43 | uint16_t occupied : 14; 44 | uint16_t has_inlines : 1; 45 | uint16_t bit_one : 1; 46 | preopt_cache_entry_t entries[]; 47 | }; 48 | 49 | union isa_t { 50 | uintptr_t bits; 51 | // Accessing the class requires custom ptrauth operations 52 | Class cls; 53 | }; 54 | 55 | struct cache_t { 56 | std::atomic _bucketsAndMaybeMask; 57 | union { 58 | struct { 59 | std::atomic _maybeMask; 60 | #if __LP64__ 61 | uint16_t _flags; 62 | #endif 63 | uint16_t _occupied; 64 | }; 65 | std::atomic _originalPreoptCache; 66 | }; 67 | }; 68 | 69 | struct objc_object_ { 70 | union isa_t isa; 71 | }; 72 | 73 | struct objc_class_ : objc_object_ { 74 | Class superclass; 75 | cache_t cache; // formerly cache pointer and vtable 76 | class_data_bits_t bits; 77 | }; 78 | 79 | extern "C" BOOL isSwiftObjectOrClass(id objOrClass) { 80 | Class cls = objOrClass; 81 | if (!object_isClass(objOrClass)) { 82 | cls = object_getClass(objOrClass); 83 | } 84 | 85 | class_data_bits_t rodata = ((__bridge objc_class_ *)(cls))->bits; 86 | 87 | if (@available(macOS 10.14.4, iOS 12.2, tvOS 12.2, watchOS 5.2, *)) { 88 | return rodata & FAST_IS_SWIFT_STABLE; 89 | } else { 90 | return rodata & FAST_IS_SWIFT_LEGACY; 91 | } 92 | } 93 | 94 | @implementation RFView 95 | 96 | - (id)initWithColor:(UIColor *)color frame:(CGRect)frame { 97 | self = [super init]; 98 | if (self) { 99 | _color = color; 100 | _frame = frame; 101 | _alpha = 1; 102 | } 103 | 104 | return self; 105 | } 106 | 107 | - (void)layoutSubviews { 108 | 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /ReflexTests/ReflexTests-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "ReflexObjcTests.h" 6 | -------------------------------------------------------------------------------- /ReflexTests/ReflexTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReflexTests.swift 3 | // ReflexTests 4 | // 5 | // Created by Tanner Bennett on 4/8/21. 6 | // 7 | 8 | import XCTest 9 | import Combine 10 | import Echo 11 | @testable import Reflex 12 | 13 | class ReflexTests: XCTestCase { 14 | var bob = Employee(name: "Bob", age: 55, position: "Programmer") 15 | lazy var employee = reflectClass(bob)! 16 | lazy var person = employee.superclassMetadata! 17 | lazy var employeeFields = employee.descriptor.fields 18 | lazy var personFields = person.descriptor.fields 19 | 20 | func assertFieldsEqual(_ expectedNames: [String], _ fields: FieldDescriptor) { 21 | let fieldNames: Set = Set(fields.records.map(\.name)) 22 | XCTAssertEqual(fieldNames, Set(expectedNames)) 23 | } 24 | 25 | func testPointerSemantics() { 26 | let point = Point(x: 5, y: 7) 27 | let yval = withUnsafeBytes(of: point) { (ptr) -> Int in 28 | return ptr.load(fromByteOffset: MemoryLayout.size, as: Int.self) 29 | } 30 | 31 | XCTAssertEqual(yval, 7) 32 | } 33 | 34 | func testKVCGetters() { 35 | assertFieldsEqual(["position", "salary", "cubicleSize"], employeeFields) 36 | assertFieldsEqual(["name", "age"], personFields) 37 | 38 | XCTAssertEqual(bob.position, employee.getValue(forKey: "position", from: bob)) 39 | XCTAssertEqual(bob.salary, employee.getValue(forKey: "salary", from: bob)) 40 | XCTAssertEqual(bob.cubicleSize, employee.getValue(forKey: "cubicleSize", from: bob)) 41 | XCTAssertEqual(bob.name, person.getValue(forKey: "name", from: bob)) 42 | XCTAssertEqual(bob.age, person.getValue(forKey: "age", from: bob)) 43 | } 44 | 45 | func testKVCSetters() { 46 | person.set(value: "Robert", forKey: "name", on: &bob) 47 | XCTAssertEqual("Robert", bob.name) 48 | XCTAssertEqual(bob.name, person.getValue(forKey: "name", from: bob)) 49 | 50 | person.set(value: 23, forKey: "age", on: &bob) 51 | XCTAssertEqual(23, bob.age) 52 | XCTAssertEqual(bob.age, person.getValue(forKey: "age", from: bob)) 53 | 54 | employee.set(value: "Janitor", forKey: "position", on: &bob) 55 | XCTAssertEqual("Janitor", bob.position) 56 | XCTAssertEqual(bob.position, employee.getValue(forKey: "position", from: bob)) 57 | 58 | employee.set(value: 3.14159, forKey: "salary", on: &bob) 59 | XCTAssertEqual(3.14159, bob.salary) 60 | XCTAssertEqual(bob.salary, employee.getValue(forKey: "salary", from: bob)) 61 | } 62 | 63 | func testTypeNames() { 64 | XCTAssertEqual(person.descriptor.name, "Person") 65 | } 66 | 67 | func testAbilityToDetectSwiftTypes() { 68 | let nonSwiftObjects: [Any] = [ 69 | NSObject.self, 70 | NSObject(), 71 | UIView.self, 72 | UIView(), 73 | "a string", 74 | 12345, 75 | self.superclass!, 76 | ] 77 | 78 | let swiftObjects: [Any] = [ 79 | ReflexTests.self, 80 | self, 81 | Person.self, 82 | bob, 83 | [1, 2, 3], 84 | [Point(x: 1, y: 2)] 85 | ] 86 | 87 | for obj in swiftObjects { 88 | XCTAssertTrue(isSwiftObjectOrClass(obj)) 89 | } 90 | for obj in nonSwiftObjects { 91 | XCTAssertFalse(isSwiftObjectOrClass(obj)) 92 | } 93 | } 94 | 95 | @available(iOS 13.0, *) 96 | func testTypeDescriptions() { 97 | typealias LongPublisher = Publishers.CombineLatest,AnyPublisher> 98 | 99 | XCTAssertEqual("Any", reflect(Any.self).description) 100 | XCTAssertEqual("AnyObject", reflect(AnyObject.self).description) 101 | XCTAssertEqual("AnyClass", reflect(AnyClass.self).description) 102 | 103 | XCTAssertEqual("String?", reflect(String?.self).description) 104 | XCTAssertEqual("Counter", reflect(Counter.self).description) 105 | XCTAssertEqual("Array", reflect([Int].self).description) 106 | XCTAssertEqual("(id: Int, 1: Person)", reflect((id: Int, Person).self).description) 107 | XCTAssertEqual("Counter", reflect(Counter.self).description) 108 | XCTAssertEqual("Array>", reflect([Counter].self).description) 109 | XCTAssertEqual("CombineLatest, AnyPublisher>", 110 | reflect(LongPublisher.self).description 111 | ) 112 | 113 | let ikur: (inout Person) -> Bool = isKnownUniquelyReferenced 114 | XCTAssertEqual("(ReflexTests) -> () -> ()", reflect(Self.testTypeDescriptions).description) 115 | XCTAssertEqual("(Person) -> Bool", reflect(ikur).description) 116 | } 117 | 118 | func testValueDescriptions() { 119 | 120 | } 121 | 122 | func testTypeEncodings() { 123 | let rect = reflect(CGRect.self) 124 | XCTAssertEqual(rect.typeEncodingString, "{CGRect={CGPoint=dd}{CGSize=dd}}") 125 | 126 | let size = reflect(Size.self) 127 | XCTAssertEqual(size.typeEncodingString, "{Size=qq}") 128 | } 129 | 130 | func testStructFieldLabels() { 131 | let mirror = SwiftMirror(reflecting: Sprite.self) 132 | let structIvar = mirror.ivars.first(where: { $0.name == "boundingBox" })! 133 | 134 | let info = structIvar.auxiliaryInfo(forKey: FLEXAuxiliarynfoKeyFieldLabels) 135 | if let labels = info as? [String: [String]] { 136 | XCTAssertEqual(labels.count, 3) 137 | XCTAssertEqual(labels["{Rect={Point=qq}{Size=qq}}"], ["Point origin", "Size size"]) 138 | XCTAssertEqual(labels["{Point=qq}"], ["Int x", "Int y"]) 139 | XCTAssertEqual(labels["{Size=qq}"], ["Int width", "Int height"]) 140 | } else { 141 | XCTFail() 142 | } 143 | } 144 | 145 | func testSwiftMirrorAvailable() { 146 | XCTAssertNotNil(NSClassFromString("FLEXSwiftMirror")) 147 | } 148 | 149 | func testSwiftMirror() { 150 | let slider = RFSlider(color: .red, frame: .zero) 151 | let sliderMirror = SwiftMirror(reflecting: slider) 152 | let bob = Employee(name: "Bob", age: 45, position: "Programmer", salary: 100_000) 153 | let employeeMirror = SwiftMirror(reflecting: bob) 154 | 155 | XCTAssertEqual(sliderMirror.ivars.count, 8) 156 | XCTAssertEqual(sliderMirror.properties.count, 1) 157 | XCTAssertEqual(sliderMirror.methods.count, 6) 158 | XCTAssertEqual(sliderMirror.protocols.count, 1) 159 | 160 | slider.tag = 0xAABB 161 | 162 | // Swift mirror // 163 | 164 | let smirror = Mirror(reflecting: slider) 165 | let smtag = smirror.children.filter { $0.label == "tag" }.first!.value as! Int 166 | XCTAssertEqual(smtag, slider.tag) 167 | 168 | // Echo // 169 | let tagp = sliderMirror.ivars.filter { $0.name == "tag" }.first! 170 | let titlep = sliderMirror.ivars.filter { $0.name == "title" }.first! 171 | let subtitlep = sliderMirror.ivars.filter { $0.name == "subtitle" }.first! 172 | let sizep = employeeMirror.ivars.filter { $0.name == "cubicleSize" }.first! 173 | 174 | // Read 175 | let tag: Int = tagp.getValue(slider) as! Int 176 | XCTAssertEqual(tag, slider.tag) 177 | // Write 178 | tagp.setValue(0xDDCC, on: slider) 179 | XCTAssertEqual(0xDDCC, slider.tag) 180 | let newTag = tagp.getValue(slider) as! Int 181 | XCTAssertEqual(newTag, slider.tag) 182 | 183 | // Type encodings 184 | XCTAssertEqual(tagp.type, .longLong) 185 | XCTAssertEqual(tagp.typeEncoding, "q") 186 | XCTAssertEqual(tagp.description, "NSInteger tag") 187 | XCTAssertEqual(titlep.description, "String title") 188 | XCTAssertEqual(subtitlep.description, "String? subtitle") 189 | XCTAssertEqual(sizep.description, "Size cubicleSize") 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /ReflexTests/SampleTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SampleTypes.swift 3 | // ReflexTests 4 | // 5 | // Created by Tanner Bennett on 4/12/21. 6 | // Copyright © 2021 Tanner Bennett. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Counter { 12 | var count: T = 5 13 | } 14 | 15 | struct Point: Equatable { 16 | var x: Int = 0 17 | var y: Int = 0 18 | } 19 | 20 | struct Size: Equatable { 21 | var width: Int = 0 22 | var height: Int = 0 23 | } 24 | 25 | struct Rect: Equatable { 26 | static let zero = Rect(origin: .init(), size: .init()) 27 | var origin: Point 28 | var size: Size 29 | } 30 | 31 | class Sprite { 32 | let boundingBox: Rect = .zero 33 | } 34 | 35 | class Person: Equatable { 36 | var name: String 37 | var age: Int 38 | 39 | var tuple: (String, Int) { 40 | return (self.name, self.age) 41 | } 42 | 43 | internal init(name: String, age: Int) { 44 | self.name = name 45 | self.age = age 46 | } 47 | 48 | static func == (lhs: Person, rhs: Person) -> Bool { 49 | return lhs.name == rhs.name && lhs.age == rhs.age 50 | } 51 | 52 | func sayHello() { 53 | print("Hello!") 54 | } 55 | } 56 | 57 | class Employee: Person { 58 | private(set) var position: String 59 | private(set) var salary: Double 60 | let cubicleSize = Size(width: 5, height: 7) 61 | 62 | var job: (position: String, salary: Double) { 63 | return (self.position, self.salary) 64 | } 65 | 66 | internal init(name: String, age: Int, position: String, salary: Double = 60_000) { 67 | self.position = position 68 | self.salary = salary 69 | super.init(name: name, age: age) 70 | } 71 | 72 | func promote() -> (position: String, salary: Double) { 73 | self.position += "+" 74 | self.salary *= 1.05 75 | 76 | return self.job 77 | } 78 | } 79 | 80 | protocol Slidable { 81 | var value: Double { get set } 82 | } 83 | 84 | /// 1 protocol (`Slidable`, `Equatable` does not appear?) 85 | /// 5 ivars (`smooth` is included) 86 | /// 1 property (the `@objc smooth`) 87 | /// 5 methods 88 | /// - `initWithColor:frame:` 89 | /// - `smooth` 90 | /// - `init` 91 | /// - `setRange:` 92 | /// - `setSmooth:` 93 | class RFSlider: RFView, Slidable { 94 | var value = 0.0 95 | var minValue = 0.0 96 | var maxValue = 1.0 97 | var step = 0.1 98 | @objc var smooth = false 99 | 100 | var title = "" 101 | var subtitle: String? = nil 102 | var tag = 0 103 | 104 | func zero() { 105 | value = self.minValue 106 | } 107 | 108 | @objc 109 | func setRange(_ range: NSRange) { 110 | self.minValue = Double(range.location) 111 | self.maxValue = self.minValue + Double(range.length) 112 | 113 | if self.value < self.minValue || self.value > self.maxValue { 114 | self.zero() 115 | } 116 | } 117 | 118 | static func == (l: RFSlider, r: RFSlider) -> Bool { 119 | return l.value == r.value 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /libflex.tbd: -------------------------------------------------------------------------------- 1 | --- !tapi-tbd 2 | tbd-version: 4 3 | targets: [ armv7-ios, armv7s-ios, arm64-ios, arm64e-ios, x86_64 ] 4 | uuids: 5 | - target: armv7-ios 6 | value: 616EEED2-13DA-3C36-97AC-990446C4FFF3 7 | - target: armv7s-ios 8 | value: B8045317-D8E3-3E83-8B01-E141753DBB68 9 | - target: arm64-ios 10 | value: 4EF19930-43FE-3FC0-94B2-030CA98A1EC1 11 | - target: arm64e-ios 12 | value: 3A1A31E1-6D03-33C4-A0C1-A230DB9078D4 13 | flags: [ not_app_extension_safe ] 14 | install-name: '/Library/MobileSubstrate/DynamicLibraries/libFLEX.dylib' 15 | current-version: 1 16 | compatibility-version: 1 17 | exports: 18 | - targets: [ armv7-ios, armv7s-ios, arm64-ios, arm64e-ios ] 19 | symbols: [ _FLEXAuxiliarynfoKeyFieldLabels, 20 | _FLEXConstructorsShouldRun, _FLEXGetAllIvars, 21 | _FLEXGetAllMethods, _FLEXGetAllProperties, 22 | _FLEXGetAllSubclasses, _FLEXGetClassHierarchy, 23 | _FLEXGetConformedProtocols, _FLEXGetSizeAndAlignment, 24 | _FLEXIsSwiftObjectOrClass, _FLEXKnownUnsafeClassList, 25 | _FLEXKnownUnsafeClassNames, _FLEXKnownUnsafeClasses, 26 | _FLEXKnownUnsafeIvars, _FLEXPointerIsReadable, 27 | _FLEXPointerIsValidObjcObject, 28 | _FLEXRuntimeUtilityErrorDomain, 29 | _FLEXTypeEncodingString, _FLEXVersionNumber, 30 | _FLEXVersionString, __UnsafeClasses, 31 | _kCarouselCellReuseIdentifier, _kCarouselItemSpacing, 32 | _kFHSSmallZOffset, 33 | _kFHSViewControllerExcludeFLEXWindows, 34 | _kFLEXCodeFontCell, _kFLEXDBQueryRowCellReuse, 35 | _kFLEXDebounceFast, _kFLEXDebounceForAsyncSearch, 36 | _kFLEXDebounceForExpensiveIO, _kFLEXDebounceInstant, 37 | _kFLEXDefaultCell, 38 | _kFLEXDefaultsDisableOSLogForceASLKey, 39 | _kFLEXDefaultsHidePrivateMethodsKey, 40 | _kFLEXDefaultsHidePropertyIvarsKey, 41 | _kFLEXDefaultsHidePropertyMethodsKey, 42 | _kFLEXDefaultsHideVariablePreviewsKey, 43 | _kFLEXDefaultsNetworkHostDenylistKey, 44 | _kFLEXDefaultsNetworkObserverEnabledKey, 45 | _kFLEXDefaultsNetworkObserverLastModeKey, 46 | _kFLEXDefaultsRegisterJSONExplorerKey, 47 | _kFLEXDefaultsShowMethodOverridesKey, 48 | _kFLEXDefaultsToolbarTopMarginKey, 49 | _kFLEXDefaultsiOSPersistentOSLogKey, 50 | _kFLEXDetailCell, _kFLEXKeyValueCell, 51 | _kFLEXKeychainAccountKey, _kFLEXKeychainClassKey, 52 | _kFLEXKeychainCreatedAtKey, 53 | _kFLEXKeychainDescriptionKey, 54 | _kFLEXKeychainErrorDomain, _kFLEXKeychainGroupKey, 55 | _kFLEXKeychainLabelKey, 56 | _kFLEXKeychainLastModifiedKey, 57 | _kFLEXKeychainWhereKey, _kFLEXKnownUnsafeClassCount, 58 | _kFLEXMultilineCell, _kFLEXMultilineDetailCell, 59 | _kFLEXNetworkObserverEnabledStateChangedNotification, 60 | _kFLEXNetworkRecorderNewTransactionNotification, 61 | _kFLEXNetworkRecorderResponseCacheLimitDefaultsKey, 62 | _kFLEXNetworkRecorderTransactionUpdatedNotification, 63 | _kFLEXNetworkRecorderTransactionsClearedNotification, 64 | _kFLEXNetworkRecorderUserInfoTransactionKey, 65 | _kFLEXNetworkTransactionCellIdentifier, 66 | _kFLEXNumberOfImplicitArgs, 67 | _kFLEXPropertyAttributeKeyBackingIvarName, 68 | _kFLEXPropertyAttributeKeyCopy, 69 | _kFLEXPropertyAttributeKeyCustomGetter, 70 | _kFLEXPropertyAttributeKeyCustomSetter, 71 | _kFLEXPropertyAttributeKeyDynamic, 72 | _kFLEXPropertyAttributeKeyGarbageCollectable, 73 | _kFLEXPropertyAttributeKeyNonAtomic, 74 | _kFLEXPropertyAttributeKeyOldStyleTypeEncoding, 75 | _kFLEXPropertyAttributeKeyReadOnly, 76 | _kFLEXPropertyAttributeKeyRetain, 77 | _kFLEXPropertyAttributeKeyTypeEncoding, 78 | _kFLEXPropertyAttributeKeyWeak, 79 | _kFLEXSystemLogCellIdentifier, 80 | _kFRECreateTableClassCommand, 81 | _kFRECreateTableClassConformanceCommand, 82 | _kFRECreateTableIvarCommand, 83 | _kFRECreateTableMachOCommand, 84 | _kFRECreateTableMethodCommand, 85 | _kFRECreateTableMethodSignatureCommand, 86 | _kFRECreateTablePropertyCommand, 87 | _kFRECreateTableProtocolCommand, 88 | _kFRECreateTableProtocolConformanceCommand, 89 | _kFRECreateTableProtocolPropertyCommand, 90 | _kFRECreateTableSelectorCommand, 91 | _kFRECreateTableTypeEncodingCommand, 92 | _kFRECreateTableTypeSignatureCommand, 93 | _kFREEnableForeignKeys, _kFREInsertClass, 94 | _kFREInsertClassConformance, _kFREInsertImage, 95 | _kFREInsertIvar, _kFREInsertMethod, 96 | _kFREInsertMethodSignature, _kFREInsertProperty, 97 | _kFREInsertProtocol, _kFREInsertProtocolConformance, 98 | _kFREInsertProtocolMember, _kFREInsertSelector, 99 | _kFREInsertTypeEncoding, _kFREInsertTypeSignature, 100 | _kFREUpdateClassSetSuper, _kHeaderVerticalInset, 101 | _orig_os_log_shim_enabled, _os_log_shim_enabled ] 102 | objc-classes: [ FHSRangeSlider, FHSSnapshotNodes, FHSSnapshotView, 103 | FHSView, FHSViewController, FHSViewSnapshot, 104 | FLEXASLLogController, FLEXActionShortcut, 105 | FLEXAddressExplorerCoordinator, FLEXAlert, 106 | FLEXAlertAction, FLEXArgumentInputColorView, 107 | FLEXArgumentInputDateView, FLEXArgumentInputFontView, 108 | FLEXArgumentInputFontsPickerView, 109 | FLEXArgumentInputNotSupportedView, 110 | FLEXArgumentInputNumberView, 111 | FLEXArgumentInputObjectView, 112 | FLEXArgumentInputStringView, 113 | FLEXArgumentInputStructView, 114 | FLEXArgumentInputSwitchView, 115 | FLEXArgumentInputTextView, FLEXArgumentInputView, 116 | FLEXArgumentInputViewFactory, FLEXBlockDescription, 117 | FLEXBlockShortcuts, FLEXBookmarkManager, 118 | FLEXBookmarksViewController, FLEXBundleShortcuts, 119 | FLEXCarouselCell, FLEXClassBuilder, FLEXClassShortcuts, 120 | FLEXCodeFontCell, FLEXCollectionContentSection, 121 | FLEXColor, FLEXColorComponentInputView, 122 | FLEXColorPreviewBox, FLEXColorPreviewSection, 123 | FLEXCookiesViewController, FLEXDBQueryRowCell, 124 | FLEXDefaultEditorViewController, 125 | FLEXDefaultsContentSection, FLEXExplorerToolbar, 126 | FLEXExplorerToolbarItem, FLEXExplorerViewController, 127 | FLEXFieldEditorView, FLEXFieldEditorViewController, 128 | FLEXFileBrowserController, 129 | FLEXFileBrowserSearchOperation, 130 | FLEXFileBrowserTableViewCell, 131 | FLEXFilteringTableViewController, 132 | FLEXFirebaseSetDataInfo, FLEXFirebaseTransaction, 133 | FLEXGlobalsEntry, FLEXGlobalsSection, 134 | FLEXGlobalsViewController, FLEXHTTPTransaction, 135 | FLEXHTTPTransactionDetailController, 136 | FLEXHeapEnumerator, FLEXHierarchyTableViewCell, 137 | FLEXHierarchyTableViewController, 138 | FLEXHierarchyViewController, 139 | FLEXImagePreviewViewController, FLEXImageShortcuts, 140 | FLEXInternalRequestState, FLEXIvar, FLEXIvarBuilder, 141 | FLEXKBToolbarButton, FLEXKBToolbarSuggestedButton, 142 | FLEXKeyPathSearchController, 143 | FLEXKeyValueTableViewCell, 144 | FLEXKeyboardHelpViewController, FLEXKeyboardToolbar, 145 | FLEXKeychain, FLEXKeychainQuery, 146 | FLEXKeychainViewController, FLEXLayerShortcuts, 147 | FLEXLiveObjectsController, FLEXMITMDataSource, 148 | FLEXManager, FLEXMetadataSection, FLEXMethod, 149 | FLEXMethodBase, FLEXMethodCallingViewController, 150 | FLEXMethodDescription, FLEXMirror, 151 | FLEXMultiColumnTableView, 152 | FLEXMultilineDetailTableViewCell, 153 | FLEXMultilineTableViewCell, FLEXMutableListSection, 154 | FLEXMutablePropertyAttributes, FLEXNSDataShortcuts, 155 | FLEXNSStringShortcuts, FLEXNavigationController, 156 | FLEXNetworkCurlLogger, FLEXNetworkDetailRow, 157 | FLEXNetworkDetailSection, 158 | FLEXNetworkMITMViewController, FLEXNetworkObserver, 159 | FLEXNetworkRecorder, FLEXNetworkSettingsController, 160 | FLEXNetworkTransaction, FLEXNetworkTransactionCell, 161 | FLEXOSLogController, FLEXObjcRuntimeViewController, 162 | FLEXObjectExplorer, FLEXObjectExplorerDefaults, 163 | FLEXObjectExplorerFactory, 164 | FLEXObjectExplorerViewController, 165 | FLEXObjectListViewController, FLEXObjectRef, 166 | FLEXProperty, FLEXPropertyAttributes, FLEXProtocol, 167 | FLEXProtocolBuilder, FLEXRealmDatabaseManager, 168 | FLEXResources, FLEXRuntimeBrowserToolbar, 169 | FLEXRuntimeClient, FLEXRuntimeController, 170 | FLEXRuntimeExporter, FLEXRuntimeKeyPath, 171 | FLEXRuntimeKeyPathTokenizer, FLEXRuntimeUtility, 172 | FLEXSQLResult, FLEXSQLiteDatabaseManager, 173 | FLEXScopeCarousel, FLEXSearchToken, FLEXShortcut, 174 | FLEXShortcutsFactory, FLEXShortcutsSection, 175 | FLEXSingleRowSection, FLEXStaticMetadata, 176 | FLEXStaticMetadata_Class, FLEXSubtitleTableViewCell, 177 | FLEXSystemLogCell, FLEXSystemLogMessage, 178 | FLEXSystemLogViewController, FLEXTabList, 179 | FLEXTableColumnHeader, 180 | FLEXTableContentViewController, FLEXTableLeftCell, 181 | FLEXTableListViewController, 182 | FLEXTableRowDataViewController, FLEXTableView, 183 | FLEXTableViewCell, FLEXTableViewController, 184 | FLEXTableViewSection, FLEXTabsViewController, 185 | FLEXTypeEncodingParser, FLEXUIAppShortcuts, 186 | FLEXURLTransaction, FLEXUtility, 187 | FLEXVariableEditorViewController, 188 | FLEXViewControllerShortcuts, 189 | FLEXViewControllersViewController, FLEXViewShortcuts, 190 | FLEXWebViewController, FLEXWebsocketTransaction, 191 | FLEXWindow, FLEXWindowManagerController, OSCache, 192 | OSCacheEntry, OSCache_Private ] 193 | objc-ivars: [ FLEXCollectionContentSection._cachedCollection, 194 | FLEXCollectionContentSection._collection, 195 | FLEXCollectionContentSection._collectionFuture, 196 | FLEXMethodBase._flex_description, 197 | FLEXMethodBase._implementation, FLEXMethodBase._name, 198 | FLEXMethodBase._selector, 199 | FLEXMethodBase._typeEncoding, 200 | FLEXNetworkTransaction._primaryDescription, 201 | FLEXNetworkTransaction._secondaryDescription, 202 | FLEXNetworkTransaction._tertiaryDescription, 203 | FLEXPropertyAttributes._backingIvar, 204 | FLEXPropertyAttributes._count, 205 | FLEXPropertyAttributes._customGetter, 206 | FLEXPropertyAttributes._customSetter, 207 | FLEXPropertyAttributes._dictionary, 208 | FLEXPropertyAttributes._fullDeclaration, 209 | FLEXPropertyAttributes._isCopy, 210 | FLEXPropertyAttributes._isDynamic, 211 | FLEXPropertyAttributes._isGarbageCollectable, 212 | FLEXPropertyAttributes._isNonatomic, 213 | FLEXPropertyAttributes._isReadOnly, 214 | FLEXPropertyAttributes._isRetained, 215 | FLEXPropertyAttributes._isWeak, 216 | FLEXPropertyAttributes._list, 217 | FLEXPropertyAttributes._oldTypeEncoding, 218 | FLEXPropertyAttributes._string, 219 | FLEXPropertyAttributes._typeEncoding, 220 | FLEXStaticMetadata._name, 221 | FLEXTableViewSection._title, 222 | FLEXVariableEditorViewController._commitHandler, 223 | FLEXVariableEditorViewController._data, 224 | FLEXVariableEditorViewController._target ] 225 | undefineds: 226 | - targets: [ armv7-ios ] 227 | symbols: [ __Unwind_SjLj_Register, __Unwind_SjLj_Resume, 228 | __Unwind_SjLj_Unregister, ___gxx_personality_sj0, 229 | ___modsi3, ___umodsi3, _ceil, _floor, 230 | _objc_msgSendSuper2_stret, _objc_msgSend_stret, _round, 231 | _vm_region ] 232 | - targets: [ arm64-ios ] 233 | symbols: [ __Unwind_Resume, ___gxx_personality_v0 ] 234 | - targets: [ armv7-ios, arm64-ios ] 235 | symbols: [ _CFDictionaryCreateMutable, _CFDictionaryGetValue, 236 | _CFDictionarySetValue, _CFRelease, _CFRetain, 237 | _CFSetAddValue, _CFSetContainsValue, _CFSetCreate, 238 | _CFSetCreateMutable, _CFSetRemoveAllValues, 239 | _CGContextAddLineToPoint, 240 | _CGContextFillEllipseInRect, _CGContextMoveToPoint, 241 | _CGContextSetFillColorWithColor, 242 | _CGContextSetLineWidth, 243 | _CGContextSetStrokeColorWithColor, 244 | _CGContextStrokePath, _CGImageCreateWithImageInRect, 245 | _CGImageSourceCreateThumbnailAtIndex, 246 | _CGImageSourceCreateWithData, _CGRectContainsPoint, 247 | _CGRectGetHeight, _CGRectGetMaxX, _CGRectGetMaxY, 248 | _CGRectGetMidX, _CGRectGetMidY, _CGRectGetMinX, 249 | _CGRectGetMinY, _CGRectGetWidth, _CGRectIntersectsRect, 250 | _CGRectIsEmpty, _CGRectOffset, _CGRectZero, _CGSizeZero, 251 | _NSBackgroundColorAttributeName, 252 | _NSCalendarIdentifierGregorian, _NSClassFromString, 253 | _NSFileCreationDate, _NSFileTypeDirectory, 254 | _NSFontAttributeName, 255 | _NSForegroundColorAttributeName, 256 | _NSGetSizeAndAlignment, _NSHomeDirectory, 257 | _NSInternalInconsistencyException, 258 | _NSInvalidArgumentException, 259 | _NSLocalizedDescriptionKey, _NSLog, _NSRangeException, 260 | _NSSearchPathForDirectoriesInDomains, 261 | _NSSelectorFromString, _NSStringFromClass, 262 | _NSStringFromProtocol, _NSStringFromSelector, 263 | _NSTemporaryDirectory, _NSURLErrorDomain, 264 | _OBJC_EHTYPE_id, _SecItemAdd, _SecItemCopyMatching, 265 | _SecItemDelete, _SecItemUpdate, 266 | _UIApplicationDidReceiveMemoryWarningNotification, 267 | _UIContentSizeCategoryDidChangeNotification, 268 | _UIEdgeInsetsZero, _UIFontTextStyleBody, 269 | _UIFontTextStyleHeadline, 270 | _UIFontTextStyleSubheadline, _UIFontWeightRegular, 271 | _UIFontWeightSemibold, 272 | _UIGraphicsBeginImageContextWithOptions, 273 | _UIGraphicsEndImageContext, 274 | _UIGraphicsGetCurrentContext, 275 | _UIGraphicsGetImageFromCurrentImageContext, 276 | _UIImageWriteToSavedPhotosAlbum, 277 | _UIKeyInputDownArrow, _UIKeyInputEscape, 278 | _UIKeyInputLeftArrow, _UIKeyInputRightArrow, 279 | _UIKeyInputUpArrow, _UIKeyboardDidShowNotification, 280 | _UIKeyboardFrameEndUserInfoKey, 281 | _UIKeyboardWillHideNotification, 282 | _UILayoutFittingCompressedSize, _UIRectFill, 283 | _UITableViewAutomaticDimension, 284 | _UIViewNoIntrinsicMetric, _UIWindowLevelStatusBar, 285 | __Block_object_assign, __Block_object_dispose, 286 | __NSConcreteGlobalBlock, __NSConcreteStackBlock, 287 | __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev, 288 | ___CFConstantStringClassReference, ___NSArray0__, 289 | ___assert_rtn, ___memcpy_chk, ___objc_personality_v0, 290 | ___stack_chk_fail, ___stack_chk_guard, 291 | __dispatch_main_q, __dyld_get_image_header, 292 | __dyld_get_image_vmaddr_slide, __dyld_image_count, 293 | __dyld_register_func_for_add_image, 294 | __objc_empty_cache, _arc4random, _asl_get, _asl_new, 295 | _asl_next, _asl_release, _asl_search, _asl_set_query, 296 | _atoll, _calloc, _class_addIvar, _class_addMethod, 297 | _class_addProperty, _class_addProtocol, 298 | _class_copyIvarList, _class_copyMethodList, 299 | _class_copyPropertyList, _class_copyProtocolList, 300 | _class_getClassMethod, _class_getImageName, 301 | _class_getInstanceMethod, _class_getInstanceSize, 302 | _class_getInstanceVariable, 303 | _class_getMethodImplementation, _class_getName, 304 | _class_getProperty, _class_getSuperclass, 305 | _class_getVersion, _class_isMetaClass, 306 | _class_replaceMethod, _class_replaceProperty, 307 | _class_setSuperclass, _dispatch_after, _dispatch_async, 308 | _dispatch_get_global_queue, _dispatch_once, 309 | _dispatch_once_f, _dispatch_queue_create, 310 | _dispatch_sync, _dispatch_time, _dladdr, _dlopen, _dlsym, 311 | _fclose, _fopen, _fread, _free, _fseek, _ftell, _getenv, 312 | _imp_implementationWithBlock, _inflate, _inflateEnd, 313 | _inflateInit2_, _ivar_getName, _ivar_getOffset, 314 | _ivar_getTypeEncoding, _kCAAlignmentCenter, 315 | _kCATruncationEnd, _kCFAllocatorDefault, _kCFNull, 316 | _kCGImageSourceCreateThumbnailFromImageAlways, 317 | _kCGImageSourceCreateThumbnailWithTransform, 318 | _kCGImageSourceThumbnailMaxPixelSize, 319 | _kSecAttrAccessGroup, _kSecAttrAccessible, 320 | _kSecAttrAccount, _kSecAttrLabel, _kSecAttrService, 321 | _kSecAttrSynchronizable, _kSecAttrSynchronizableAny, 322 | _kSecClass, _kSecClassGenericPassword, _kSecMatchLimit, 323 | _kSecMatchLimitAll, _kSecMatchLimitOne, 324 | _kSecReturnAttributes, _kSecReturnData, _kSecValueData, 325 | _mach_task_self_, _malloc, _malloc_get_all_zones, 326 | _malloc_size, _memcmp, _memset, _method_copyArgumentType, 327 | _method_exchangeImplementations, 328 | _method_getDescription, _method_getImplementation, 329 | _method_getName, _method_getNumberOfArguments, 330 | _method_getTypeEncoding, _method_setImplementation, 331 | _mprotect, _objc_alloc, _objc_allocateClassPair, 332 | _objc_allocateProtocol, _objc_autorelease, 333 | _objc_autoreleaseReturnValue, _objc_begin_catch, 334 | _objc_copyClassList, _objc_copyClassNamesForImage, 335 | _objc_copyImageNames, _objc_copyProtocolList, 336 | _objc_copyWeak, _objc_destroyWeak, _objc_end_catch, 337 | _objc_enumerationMutation, _objc_exception_throw, 338 | _objc_getAssociatedObject, _objc_getClass, 339 | _objc_getClassList, _objc_getMetaClass, 340 | _objc_getProperty, _objc_initWeak, 341 | _objc_loadWeakRetained, _objc_lookUpClass, 342 | _objc_msgSend, _objc_msgSendSuper2, 343 | _objc_registerClassPair, _objc_registerProtocol, 344 | _objc_release, _objc_retain, _objc_retainAutorelease, 345 | _objc_retainAutoreleaseReturnValue, 346 | _objc_retainAutoreleasedReturnValue, 347 | _objc_retainBlock, _objc_setAssociatedObject, 348 | _objc_setProperty_atomic, 349 | _objc_setProperty_nonatomic_copy, _objc_storeStrong, 350 | _objc_storeWeak, _objc_sync_enter, _objc_sync_exit, 351 | _objc_unsafeClaimAutoreleasedReturnValue, 352 | _object_getClass, _object_getIvar, _object_isClass, 353 | _object_setClass, _object_setIvar, _printf, 354 | _property_copyAttributeList, 355 | _property_copyAttributeValue, 356 | _property_getAttributes, _property_getName, 357 | _protocol_addMethodDescription, 358 | _protocol_addProperty, _protocol_addProtocol, 359 | _protocol_conformsToProtocol, 360 | _protocol_copyMethodDescriptionList, 361 | _protocol_copyPropertyList, 362 | _protocol_copyProtocolList, 363 | _protocol_getMethodDescription, _protocol_getName, 364 | _realloc, _rewind, _sel_getName, _sel_registerName, 365 | _sqlite3_bind_blob64, _sqlite3_bind_double, 366 | _sqlite3_bind_int64, _sqlite3_bind_null, 367 | _sqlite3_bind_parameter_index, _sqlite3_bind_text, 368 | _sqlite3_changes, _sqlite3_close, _sqlite3_column_blob, 369 | _sqlite3_column_bytes, _sqlite3_column_count, 370 | _sqlite3_column_double, _sqlite3_column_int64, 371 | _sqlite3_column_name, _sqlite3_column_text, 372 | _sqlite3_column_type, _sqlite3_data_count, 373 | _sqlite3_errmsg, _sqlite3_finalize, 374 | _sqlite3_last_insert_rowid, _sqlite3_next_stmt, 375 | _sqlite3_open, _sqlite3_prepare_v2, _sqlite3_step, 376 | _sscanf, _strchr, _strcmp, _strlen, _toupper, 377 | _vm_read_overwrite, _vm_region_64, dyld_stub_binder ] 378 | objc-classes: [ CALayer, CATransaction, NSArray, NSAssertionHandler, 379 | NSAttributedString, NSBundle, NSByteCountFormatter, 380 | NSCache, NSCalendar, NSCharacterSet, NSData, NSDate, 381 | NSDateFormatter, NSDecimalNumber, NSDictionary, 382 | NSEnumerator, NSError, NSException, NSFileManager, 383 | NSHTTPCookieStorage, NSHTTPURLResponse, NSIndexPath, 384 | NSIndexSet, NSInputStream, NSInvocation, 385 | NSJSONSerialization, NSKeyedArchiver, 386 | NSKeyedUnarchiver, NSLayoutConstraint, NSLocale, NSLock, 387 | NSMapTable, NSMethodSignature, NSMutableArray, 388 | NSMutableAttributedString, NSMutableCharacterSet, 389 | NSMutableData, NSMutableDictionary, NSMutableIndexSet, 390 | NSMutableSet, NSMutableString, NSNotificationCenter, 391 | NSNull, NSNumber, NSNumberFormatter, NSObject, NSOperation, 392 | NSOperationQueue, NSOrderedSet, NSOutputStream, 393 | NSPredicate, NSProcessInfo, 394 | NSPropertyListSerialization, NSProxy, 395 | NSRegularExpression, NSRunLoop, NSScanner, NSSet, 396 | NSSortDescriptor, NSString, NSThread, NSTimeZone, NSTimer, 397 | NSURL, NSURLCache, NSURLConnection, NSURLQueryItem, 398 | NSURLRequest, NSURLSession, NSURLSessionTask, NSUUID, 399 | NSUserDefaults, NSValue, SCNGeometry, SCNGeometryElement, 400 | SCNGeometrySource, SCNMaterial, SCNNode, SCNScene, 401 | SCNShape, SCNText, SCNView, UIActivityItemProvider, 402 | UIActivityViewController, UIAlertAction, 403 | UIAlertController, UIApplication, UIBarButtonItem, 404 | UIBezierPath, UIButton, UICollectionView, 405 | UICollectionViewCell, UICollectionViewFlowLayout, 406 | UIColor, UIControl, UIDatePicker, UIDevice, 407 | UIDocumentInteractionController, UIFont, 408 | UIGestureRecognizer, UIImage, UIImageView, UILabel, 409 | UILongPressGestureRecognizer, UIMenuController, 410 | UIMenuItem, UINavigationController, 411 | UIPanGestureRecognizer, UIPasteboard, UIPickerView, 412 | UIRefreshControl, UIScreen, UIScrollView, 413 | UISearchController, UISegmentedControl, UISlider, 414 | UISwipeGestureRecognizer, UISwitch, UITableView, 415 | UITableViewCell, UITableViewController, 416 | UITableViewHeaderFooterView, UITapGestureRecognizer, 417 | UITextField, UITextView, UIToolbar, UIView, 418 | UIViewController, UIVisualEffectView, UIWindow, 419 | WKWebView, WKWebViewConfiguration ] 420 | objc-eh-types: [ NSException ] 421 | ... 422 | --------------------------------------------------------------------------------