From cd88c06fb3172a636348e1fb62736b3f9f192b81 Mon Sep 17 00:00:00 2001 From: nghialv Date: Mon, 1 Jun 2015 17:21:07 +0900 Subject: [PATCH] first commit --- .gitignore | 19 + Cartfile | 1 + Cartfile.resolved | 2 + Carthage/Checkouts/Result/.gitignore | 8 + Carthage/Checkouts/Result/.gitmodules | 3 + Carthage/Checkouts/Result/Cartfile | 1 + Carthage/Checkouts/Result/Cartfile.resolved | 1 + .../Result/Carthage/Checkouts/Box/.gitignore | 7 + .../Box/Box.xcodeproj/project.pbxproj | 668 ++++++++++++++++++ .../xcshareddata/xcschemes/Box-Mac.xcscheme | 110 +++ .../xcshareddata/xcschemes/Box-iOS.xcscheme | 110 +++ .../Result/Carthage/Checkouts/Box/Box/Box.h | 7 + .../Carthage/Checkouts/Box/Box/Box.swift | 33 + .../Carthage/Checkouts/Box/Box/BoxType.swift | 46 ++ .../Carthage/Checkouts/Box/Box/Info.plist | 28 + .../Checkouts/Box/Box/MutableBox.swift | 27 + .../Checkouts/Box/BoxTests/BoxTests.swift | 11 + .../Checkouts/Box/BoxTests/BoxTypeTests.swift | 24 + .../Checkouts/Box/BoxTests/Info.plist | 24 + .../Box/BoxTests/MutableBoxTests.swift | 17 + .../Result/Carthage/Checkouts/Box/LICENSE | 21 + .../Result/Carthage/Checkouts/Box/README.md | 58 ++ Carthage/Checkouts/Result/LICENSE | 21 + Carthage/Checkouts/Result/README.md | 21 + .../Result/Result.xcodeproj/project.pbxproj | 656 +++++++++++++++++ .../xcschemes/Result-Mac.xcscheme | 110 +++ .../xcschemes/Result-iOS.xcscheme | 110 +++ Carthage/Checkouts/Result/Result/Info.plist | 28 + Carthage/Checkouts/Result/Result/Result.h | 8 + Carthage/Checkouts/Result/Result/Result.swift | 201 ++++++ .../Checkouts/Result/ResultTests/Info.plist | 24 + .../Result/ResultTests/ResultTests.swift | 101 +++ Future.podspec | 16 + Future.xcodeproj/project.pbxproj | 488 +++++++++++++ Future/Future.h | 19 + Future/Future.swift | 245 +++++++ Future/Info.plist | 26 + FutureTests/FutureFunctionalTests.swift | 160 +++++ FutureTests/FutureStateTests.swift | 98 +++ FutureTests/Info.plist | 24 + FutureTests/TestUtils.swift | 76 ++ LICENSE | 20 + README.md | 106 +++ 43 files changed, 3784 insertions(+) create mode 100644 .gitignore create mode 100644 Cartfile create mode 100644 Cartfile.resolved create mode 100644 Carthage/Checkouts/Result/.gitignore create mode 100644 Carthage/Checkouts/Result/.gitmodules create mode 100644 Carthage/Checkouts/Result/Cartfile create mode 100644 Carthage/Checkouts/Result/Cartfile.resolved create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/.gitignore create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-Mac.xcscheme create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-iOS.xcscheme create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.h create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.swift create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/BoxType.swift create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Info.plist create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/MutableBox.swift create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTests.swift create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTypeTests.swift create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/Info.plist create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/MutableBoxTests.swift create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/LICENSE create mode 100644 Carthage/Checkouts/Result/Carthage/Checkouts/Box/README.md create mode 100644 Carthage/Checkouts/Result/LICENSE create mode 100644 Carthage/Checkouts/Result/README.md create mode 100644 Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme create mode 100644 Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme create mode 100644 Carthage/Checkouts/Result/Result/Info.plist create mode 100644 Carthage/Checkouts/Result/Result/Result.h create mode 100644 Carthage/Checkouts/Result/Result/Result.swift create mode 100644 Carthage/Checkouts/Result/ResultTests/Info.plist create mode 100644 Carthage/Checkouts/Result/ResultTests/ResultTests.swift create mode 100644 Future.podspec create mode 100644 Future.xcodeproj/project.pbxproj create mode 100644 Future/Future.h create mode 100644 Future/Future.swift create mode 100644 Future/Info.plist create mode 100644 FutureTests/FutureFunctionalTests.swift create mode 100644 FutureTests/FutureStateTests.swift create mode 100644 FutureTests/Info.plist create mode 100644 FutureTests/TestUtils.swift create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb30d78 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +.DS_Store + +# Xcode +build/* +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +*.xcworkspace +!default.xcworkspace +xcuserdata +profile +*.moved-aside + +Carthage/Build diff --git a/Cartfile b/Cartfile new file mode 100644 index 0000000..8999379 --- /dev/null +++ b/Cartfile @@ -0,0 +1 @@ +github "antitypical/Result" == 0.4.3 diff --git a/Cartfile.resolved b/Cartfile.resolved new file mode 100644 index 0000000..0d99185 --- /dev/null +++ b/Cartfile.resolved @@ -0,0 +1,2 @@ +github "robrix/Box" "1.2.2" +github "antitypical/Result" "0.4.3" diff --git a/Carthage/Checkouts/Result/.gitignore b/Carthage/Checkouts/Result/.gitignore new file mode 100644 index 0000000..95ddb50 --- /dev/null +++ b/Carthage/Checkouts/Result/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +xcuserdata +*.xcuserdatad +*.xccheckout +*.mode* +*.pbxuser + +Carthage/Build diff --git a/Carthage/Checkouts/Result/.gitmodules b/Carthage/Checkouts/Result/.gitmodules new file mode 100644 index 0000000..a82a49f --- /dev/null +++ b/Carthage/Checkouts/Result/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Carthage/Checkouts/Box"] + path = Carthage/Checkouts/Box + url = https://github.com/robrix/Box.git diff --git a/Carthage/Checkouts/Result/Cartfile b/Carthage/Checkouts/Result/Cartfile new file mode 100644 index 0000000..c9ef8af --- /dev/null +++ b/Carthage/Checkouts/Result/Cartfile @@ -0,0 +1 @@ +github "robrix/Box" diff --git a/Carthage/Checkouts/Result/Cartfile.resolved b/Carthage/Checkouts/Result/Cartfile.resolved new file mode 100644 index 0000000..a1ad545 --- /dev/null +++ b/Carthage/Checkouts/Result/Cartfile.resolved @@ -0,0 +1 @@ +github "robrix/Box" "1.2.2" diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/.gitignore b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/.gitignore new file mode 100644 index 0000000..c945e0c --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +build +xcuserdata +*.mode* +*.pbxuser +*.xcuserdatad +*.xccheckout diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/project.pbxproj b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/project.pbxproj new file mode 100644 index 0000000..65a5b50 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/project.pbxproj @@ -0,0 +1,668 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + D470AC3D19E86128003DA6C6 /* Box.h in Headers */ = {isa = PBXBuildFile; fileRef = D470AC3C19E86128003DA6C6 /* Box.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D470AC4319E86128003DA6C6 /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D470AC3719E86128003DA6C6 /* Box.framework */; }; + D470AC4A19E86128003DA6C6 /* BoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC4919E86128003DA6C6 /* BoxTests.swift */; }; + D470AC5619E861E2003DA6C6 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5519E861E2003DA6C6 /* Box.swift */; }; + D470AC5819E86790003DA6C6 /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5719E86790003DA6C6 /* BoxType.swift */; }; + D470AC5A19E868D3003DA6C6 /* MutableBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5919E868D3003DA6C6 /* MutableBox.swift */; }; + D470AC5C19E86A2E003DA6C6 /* MutableBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5B19E86A2E003DA6C6 /* MutableBoxTests.swift */; }; + D470AC5E19E86B2C003DA6C6 /* BoxTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5D19E86B2C003DA6C6 /* BoxTypeTests.swift */; }; + F8BB81DE1A939B67001AA352 /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8BB81D31A939B66001AA352 /* Box.framework */; }; + F8BB81EC1A939C03001AA352 /* Box.h in Headers */ = {isa = PBXBuildFile; fileRef = D470AC3C19E86128003DA6C6 /* Box.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F8BB81ED1A939C09001AA352 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5519E861E2003DA6C6 /* Box.swift */; }; + F8BB81EE1A939C0D001AA352 /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5719E86790003DA6C6 /* BoxType.swift */; }; + F8BB81EF1A939C0D001AA352 /* MutableBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5919E868D3003DA6C6 /* MutableBox.swift */; }; + F8BB81F01A939C1A001AA352 /* BoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC4919E86128003DA6C6 /* BoxTests.swift */; }; + F8BB81F11A939C1A001AA352 /* BoxTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5D19E86B2C003DA6C6 /* BoxTypeTests.swift */; }; + F8BB81F21A939C1A001AA352 /* MutableBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D470AC5B19E86A2E003DA6C6 /* MutableBoxTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + D470AC4419E86128003DA6C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D470AC2E19E86128003DA6C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D470AC3619E86128003DA6C6; + remoteInfo = Box; + }; + F8BB81DF1A939B67001AA352 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D470AC2E19E86128003DA6C6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F8BB81D21A939B66001AA352; + remoteInfo = "Box-iOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + D470AC3719E86128003DA6C6 /* Box.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Box.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D470AC3B19E86128003DA6C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D470AC3C19E86128003DA6C6 /* Box.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Box.h; sourceTree = ""; }; + D470AC4219E86128003DA6C6 /* Box-MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Box-MacTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D470AC4819E86128003DA6C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D470AC4919E86128003DA6C6 /* BoxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoxTests.swift; sourceTree = ""; }; + D470AC5519E861E2003DA6C6 /* Box.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = ""; }; + D470AC5719E86790003DA6C6 /* BoxType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxType.swift; sourceTree = ""; }; + D470AC5919E868D3003DA6C6 /* MutableBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MutableBox.swift; sourceTree = ""; }; + D470AC5B19E86A2E003DA6C6 /* MutableBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MutableBoxTests.swift; sourceTree = ""; }; + D470AC5D19E86B2C003DA6C6 /* BoxTypeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxTypeTests.swift; sourceTree = ""; }; + F8BB81D31A939B66001AA352 /* Box.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Box.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F8BB81DD1A939B67001AA352 /* Box-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Box-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D470AC3319E86128003DA6C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D470AC3F19E86128003DA6C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D470AC4319E86128003DA6C6 /* Box.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8BB81CF1A939B66001AA352 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8BB81DA1A939B67001AA352 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F8BB81DE1A939B67001AA352 /* Box.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D470AC2D19E86128003DA6C6 = { + isa = PBXGroup; + children = ( + D470AC3919E86128003DA6C6 /* Box */, + D470AC4619E86128003DA6C6 /* BoxTests */, + D470AC3819E86128003DA6C6 /* Products */, + ); + sourceTree = ""; + }; + D470AC3819E86128003DA6C6 /* Products */ = { + isa = PBXGroup; + children = ( + D470AC3719E86128003DA6C6 /* Box.framework */, + D470AC4219E86128003DA6C6 /* Box-MacTests.xctest */, + F8BB81D31A939B66001AA352 /* Box.framework */, + F8BB81DD1A939B67001AA352 /* Box-iOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + D470AC3919E86128003DA6C6 /* Box */ = { + isa = PBXGroup; + children = ( + D470AC3C19E86128003DA6C6 /* Box.h */, + D470AC5519E861E2003DA6C6 /* Box.swift */, + D470AC5719E86790003DA6C6 /* BoxType.swift */, + D470AC5919E868D3003DA6C6 /* MutableBox.swift */, + D470AC3A19E86128003DA6C6 /* Supporting Files */, + ); + path = Box; + sourceTree = ""; + }; + D470AC3A19E86128003DA6C6 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D470AC3B19E86128003DA6C6 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D470AC4619E86128003DA6C6 /* BoxTests */ = { + isa = PBXGroup; + children = ( + D470AC4919E86128003DA6C6 /* BoxTests.swift */, + D470AC5D19E86B2C003DA6C6 /* BoxTypeTests.swift */, + D470AC5B19E86A2E003DA6C6 /* MutableBoxTests.swift */, + D470AC4719E86128003DA6C6 /* Supporting Files */, + ); + path = BoxTests; + sourceTree = ""; + }; + D470AC4719E86128003DA6C6 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D470AC4819E86128003DA6C6 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D470AC3419E86128003DA6C6 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D470AC3D19E86128003DA6C6 /* Box.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8BB81D01A939B66001AA352 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F8BB81EC1A939C03001AA352 /* Box.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D470AC3619E86128003DA6C6 /* Box-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = D470AC4D19E86128003DA6C6 /* Build configuration list for PBXNativeTarget "Box-Mac" */; + buildPhases = ( + D470AC3219E86128003DA6C6 /* Sources */, + D470AC3319E86128003DA6C6 /* Frameworks */, + D470AC3419E86128003DA6C6 /* Headers */, + D470AC3519E86128003DA6C6 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Box-Mac"; + productName = Box; + productReference = D470AC3719E86128003DA6C6 /* Box.framework */; + productType = "com.apple.product-type.framework"; + }; + D470AC4119E86128003DA6C6 /* Box-MacTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D470AC5019E86128003DA6C6 /* Build configuration list for PBXNativeTarget "Box-MacTests" */; + buildPhases = ( + D470AC3E19E86128003DA6C6 /* Sources */, + D470AC3F19E86128003DA6C6 /* Frameworks */, + D470AC4019E86128003DA6C6 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D470AC4519E86128003DA6C6 /* PBXTargetDependency */, + ); + name = "Box-MacTests"; + productName = BoxTests; + productReference = D470AC4219E86128003DA6C6 /* Box-MacTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + F8BB81D21A939B66001AA352 /* Box-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = F8BB81E61A939B67001AA352 /* Build configuration list for PBXNativeTarget "Box-iOS" */; + buildPhases = ( + F8BB81CE1A939B66001AA352 /* Sources */, + F8BB81CF1A939B66001AA352 /* Frameworks */, + F8BB81D01A939B66001AA352 /* Headers */, + F8BB81D11A939B66001AA352 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Box-iOS"; + productName = Box; + productReference = F8BB81D31A939B66001AA352 /* Box.framework */; + productType = "com.apple.product-type.framework"; + }; + F8BB81DC1A939B67001AA352 /* Box-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F8BB81E91A939B67001AA352 /* Build configuration list for PBXNativeTarget "Box-iOSTests" */; + buildPhases = ( + F8BB81D91A939B67001AA352 /* Sources */, + F8BB81DA1A939B67001AA352 /* Frameworks */, + F8BB81DB1A939B67001AA352 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + F8BB81E01A939B67001AA352 /* PBXTargetDependency */, + ); + name = "Box-iOSTests"; + productName = "Box-iOSTests"; + productReference = F8BB81DD1A939B67001AA352 /* Box-iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D470AC2E19E86128003DA6C6 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0610; + ORGANIZATIONNAME = "Rob Rix"; + TargetAttributes = { + D470AC3619E86128003DA6C6 = { + CreatedOnToolsVersion = 6.1; + }; + D470AC4119E86128003DA6C6 = { + CreatedOnToolsVersion = 6.1; + }; + F8BB81D21A939B66001AA352 = { + CreatedOnToolsVersion = 6.3; + }; + F8BB81DC1A939B67001AA352 = { + CreatedOnToolsVersion = 6.3; + }; + }; + }; + buildConfigurationList = D470AC3119E86128003DA6C6 /* Build configuration list for PBXProject "Box" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D470AC2D19E86128003DA6C6; + productRefGroup = D470AC3819E86128003DA6C6 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D470AC3619E86128003DA6C6 /* Box-Mac */, + D470AC4119E86128003DA6C6 /* Box-MacTests */, + F8BB81D21A939B66001AA352 /* Box-iOS */, + F8BB81DC1A939B67001AA352 /* Box-iOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D470AC3519E86128003DA6C6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D470AC4019E86128003DA6C6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8BB81D11A939B66001AA352 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8BB81DB1A939B67001AA352 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D470AC3219E86128003DA6C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D470AC5619E861E2003DA6C6 /* Box.swift in Sources */, + D470AC5819E86790003DA6C6 /* BoxType.swift in Sources */, + D470AC5A19E868D3003DA6C6 /* MutableBox.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D470AC3E19E86128003DA6C6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D470AC5C19E86A2E003DA6C6 /* MutableBoxTests.swift in Sources */, + D470AC4A19E86128003DA6C6 /* BoxTests.swift in Sources */, + D470AC5E19E86B2C003DA6C6 /* BoxTypeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8BB81CE1A939B66001AA352 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F8BB81ED1A939C09001AA352 /* Box.swift in Sources */, + F8BB81EE1A939C0D001AA352 /* BoxType.swift in Sources */, + F8BB81EF1A939C0D001AA352 /* MutableBox.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F8BB81D91A939B67001AA352 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F8BB81F01A939C1A001AA352 /* BoxTests.swift in Sources */, + F8BB81F11A939C1A001AA352 /* BoxTypeTests.swift in Sources */, + F8BB81F21A939C1A001AA352 /* MutableBoxTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + D470AC4519E86128003DA6C6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D470AC3619E86128003DA6C6 /* Box-Mac */; + targetProxy = D470AC4419E86128003DA6C6 /* PBXContainerItemProxy */; + }; + F8BB81E01A939B67001AA352 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F8BB81D21A939B66001AA352 /* Box-iOS */; + targetProxy = F8BB81DF1A939B67001AA352 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + D470AC4B19E86128003DA6C6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + D470AC4C19E86128003DA6C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D470AC4E19E86128003DA6C6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Box/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Box; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + D470AC4F19E86128003DA6C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Box/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Box; + SKIP_INSTALL = YES; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + D470AC5119E86128003DA6C6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = BoxTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D470AC5219E86128003DA6C6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = BoxTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + F8BB81E71A939B67001AA352 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/Box/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Box; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + F8BB81E81A939B67001AA352 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "$(SRCROOT)/Box/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Box; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + F8BB81EA1A939B67001AA352 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = BoxTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + }; + name = Debug; + }; + F8BB81EB1A939B67001AA352 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = BoxTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D470AC3119E86128003DA6C6 /* Build configuration list for PBXProject "Box" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D470AC4B19E86128003DA6C6 /* Debug */, + D470AC4C19E86128003DA6C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D470AC4D19E86128003DA6C6 /* Build configuration list for PBXNativeTarget "Box-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D470AC4E19E86128003DA6C6 /* Debug */, + D470AC4F19E86128003DA6C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D470AC5019E86128003DA6C6 /* Build configuration list for PBXNativeTarget "Box-MacTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D470AC5119E86128003DA6C6 /* Debug */, + D470AC5219E86128003DA6C6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F8BB81E61A939B67001AA352 /* Build configuration list for PBXNativeTarget "Box-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F8BB81E71A939B67001AA352 /* Debug */, + F8BB81E81A939B67001AA352 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F8BB81E91A939B67001AA352 /* Build configuration list for PBXNativeTarget "Box-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F8BB81EA1A939B67001AA352 /* Debug */, + F8BB81EB1A939B67001AA352 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D470AC2E19E86128003DA6C6 /* Project object */; +} diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-Mac.xcscheme b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-Mac.xcscheme new file mode 100644 index 0000000..1071191 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-Mac.xcscheme @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-iOS.xcscheme b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-iOS.xcscheme new file mode 100644 index 0000000..bce5fc5 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box.xcodeproj/xcshareddata/xcschemes/Box-iOS.xcscheme @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.h b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.h new file mode 100644 index 0000000..f02cc1c --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.h @@ -0,0 +1,7 @@ +// Copyright (c) 2014 Rob Rix. All rights reserved. + +/// Project version number for Box. +extern double BoxVersionNumber; + +/// Project version string for Box. +extern const unsigned char BoxVersionString[]; diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.swift b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.swift new file mode 100644 index 0000000..491e68e --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Box.swift @@ -0,0 +1,33 @@ +// Copyright (c) 2014 Rob Rix. All rights reserved. + +/// Wraps a type `T` in a reference type. +/// +/// Typically this is used to work around limitations of value types (for example, the lack of codegen for recursive value types and type-parameterized enums with >1 case). It is also useful for sharing a single (presumably large) value without copying it. +public final class Box: BoxType, Printable { + /// Initializes a `Box` with the given value. + public init(_ value: T) { + self.value = value + } + + + /// Constructs a `Box` with the given `value`. + public class func unit(value: T) -> Box { + return Box(value) + } + + + /// The (immutable) value wrapped by the receiver. + public let value: T + + /// Constructs a new Box by transforming `value` by `f`. + public func map(@noescape f: T -> U) -> Box { + return Box(f(value)) + } + + + // MARK: Printable + + public var description: String { + return toString(value) + } +} diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/BoxType.swift b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/BoxType.swift new file mode 100644 index 0000000..78a08d0 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/BoxType.swift @@ -0,0 +1,46 @@ +// Copyright (c) 2014 Rob Rix. All rights reserved. + +// MARK: BoxType + +/// The type conformed to by all boxes. +public protocol BoxType { + /// The type of the wrapped value. + typealias Value + + /// Initializes an intance of the type with a value. + init(_ value: Value) + + /// The wrapped value. + var value: Value { get } +} + +/// The type conformed to by mutable boxes. +public protocol MutableBoxType: BoxType { + /// The (mutable) wrapped value. + var value: Value { get set } +} + + +// MARK: Equality + +/// Equality of `BoxType`s of `Equatable` types. +/// +/// We cannot declare that e.g. `Box` conforms to `Equatable`, so this is a relatively ad hoc definition. +public func == (lhs: B, rhs: B) -> Bool { + return lhs.value == rhs.value +} + +/// Inequality of `BoxType`s of `Equatable` types. +/// +/// We cannot declare that e.g. `Box` conforms to `Equatable`, so this is a relatively ad hoc definition. +public func != (lhs: B, rhs: B) -> Bool { + return lhs.value != rhs.value +} + + +// MARK: Map + +/// Maps the value of a box into a new box. +public func map(v: B, @noescape f: B.Value -> C.Value) -> C { + return C(f(v.value)) +} diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Info.plist b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Info.plist new file mode 100644 index 0000000..b35c271 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.antitypical.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.1 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2014 Rob Rix. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/MutableBox.swift b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/MutableBox.swift new file mode 100644 index 0000000..07f266e --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/Box/MutableBox.swift @@ -0,0 +1,27 @@ +// Copyright (c) 2014 Rob Rix. All rights reserved. + +/// Wraps a type `T` in a mutable reference type. +/// +/// While this, like `Box` could be used to work around limitations of value types, it is much more useful for sharing a single mutable value such that mutations are shared. +/// +/// As with all mutable state, this should be used carefully, for example as an optimization, rather than a default design choice. Most of the time, `Box` will suffice where any `BoxType` is needed. +public final class MutableBox: MutableBoxType, Printable { + /// Initializes a `MutableBox` with the given value. + public init(_ value: T) { + self.value = value + } + + /// The (mutable) value wrapped by the receiver. + public var value: T + + /// Constructs a new MutableBox by transforming `value` by `f`. + public func map(@noescape f: T -> U) -> MutableBox { + return MutableBox(f(value)) + } + + // MARK: Printable + + public var description: String { + return toString(value) + } +} diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTests.swift b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTests.swift new file mode 100644 index 0000000..796190c --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTests.swift @@ -0,0 +1,11 @@ +// Copyright (c) 2014 Rob Rix. All rights reserved. + +import Box +import XCTest + +class BoxTests: XCTestCase { + func testBox() { + let box = Box(1) + XCTAssertEqual(box.value, 1) + } +} diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTypeTests.swift b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTypeTests.swift new file mode 100644 index 0000000..36f7594 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/BoxTypeTests.swift @@ -0,0 +1,24 @@ +// Copyright (c) 2014 Rob Rix. All rights reserved. + +import Box +import XCTest + +class BoxTypeTests: XCTestCase { + func testEquality() { + let (a, b, c) = (Box(1), Box(1), Box(2)) + XCTAssertTrue(a == b) + XCTAssertFalse(b == c) + } + + func testInequality() { + let (a, b, c) = (Box(1), Box(1), Box(2)) + XCTAssertFalse(a != b) + XCTAssertTrue(b != c) + } + + func testMap() { + let a = Box(1) + let b: Box = map(a, toString) + XCTAssertEqual(b.value, "1") + } +} diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/Info.plist b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/Info.plist new file mode 100644 index 0000000..358bdf0 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.antitypical.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/MutableBoxTests.swift b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/MutableBoxTests.swift new file mode 100644 index 0000000..c3c1150 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/BoxTests/MutableBoxTests.swift @@ -0,0 +1,17 @@ +// Copyright (c) 2014 Rob Rix. All rights reserved. + +import Box +import XCTest + +class MutableBoxTests: XCTestCase { + func testBox() { + let box = MutableBox(1) + XCTAssertEqual(box.value, 1) + } + + func testMutation() { + let box = MutableBox(1) + box.value = 2 + XCTAssertEqual(box.value, 2) + } +} diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/LICENSE b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/LICENSE new file mode 100644 index 0000000..3026ee1 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Rob Rix + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Carthage/Checkouts/Result/Carthage/Checkouts/Box/README.md b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/README.md new file mode 100644 index 0000000..b9948a0 --- /dev/null +++ b/Carthage/Checkouts/Result/Carthage/Checkouts/Box/README.md @@ -0,0 +1,58 @@ +# Box + +This is a Swift microframework which implements `Box` & `MutableBox`, with implementations of `==`/`!=` where `T`: `Equatable`. + +`Box` is typically used to work around limitations of value types: + +- recursive `struct`s/`enum`s +- type-parameterized `enum`s where more than one `case` has a value + +## Use + +Wrapping & unwrapping a `Box`: + +```swift +// Wrap: +let box = Box(1) + +// Unwrap: +let value = box.value +``` + +Changing the value of a `MutableBox`: + +```swift +// Mutation: +let mutableBox = MutableBox(1) +mutableBox.value = 2 +``` + +Building a recursive value type: + +```swift +struct BinaryTree { + let value: Int + let left: Box? + let right: Box? +} +``` + +Building a parameterized `enum`: + +```swift +enum Result { + case Success(Box) + case Failure(NSError) +} +``` + +See the sources for more details. + +## Integration + +1. Add this repo as a submodule in e.g. `External/Box`: + + git submodule add https://github.com/robrix/Box.git External/Box +2. Drag `Box.xcodeproj` into your `.xcworkspace`/`.xcodeproj`. +3. Add `Box.framework` to your target’s `Link Binary With Libraries` build phase. +4. You may also want to add a `Copy Files` phase which copies `Box.framework` (and any other framework dependencies you need) into your bundle’s `Frameworks` directory. If your target is a framework, you may instead want the client app to include `Box.framework`. diff --git a/Carthage/Checkouts/Result/LICENSE b/Carthage/Checkouts/Result/LICENSE new file mode 100644 index 0000000..3026ee1 --- /dev/null +++ b/Carthage/Checkouts/Result/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Rob Rix + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/Carthage/Checkouts/Result/README.md b/Carthage/Checkouts/Result/README.md new file mode 100644 index 0000000..cf4402d --- /dev/null +++ b/Carthage/Checkouts/Result/README.md @@ -0,0 +1,21 @@ +# Result + +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![CocoaPods](https://img.shields.io/cocoapods/v/Result.svg)](https://cocoapods.org/) + +This is a Swift µframework providing `Result`. + +`Result` values are either successful (wrapping `Value`) or failed (wrapping `Error`). This is similar to Swift’s native `Optional` type, with the addition of an error value to pass some error code, message, or object along to be logged or displayed to the user. + + +## Use + +[API documentation](http://cocoadocs.org/docsets/Result/) is in the source. + + +## Integration + +1. Add this repository as a submodule and check out its dependencies, and/or [add it to your Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile) if you’re using [carthage](https://github.com/Carthage/Carthage/) to manage your dependencies. +2. Drag `Result.xcodeproj` and `Box.xcodeproj` into your project or workspace. NB: `Result.xcworkspace` is for standalone development of Result, while `Result.xcodeproj` is for targets using Result as a dependency. +3. Link your target against `Result.framework` and `Box.framework`. +4. Application targets should ensure that the framework gets copied into their application bundle. (Framework targets should instead require the application linking them to include Result and Box.) diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj b/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ec6d774 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj @@ -0,0 +1,656 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + BE740B561AEB28AB004B478F /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE740B551AEB28AB004B478F /* Box.framework */; }; + BE740B571AEB29F7004B478F /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE740B551AEB28AB004B478F /* Box.framework */; }; + D454805D1A9572F5009D7229 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D45480681A9572F5009D7229 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D45480571A9572F5009D7229 /* Result.framework */; }; + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + D45480881A957362009D7229 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D454807D1A957361009D7229 /* Result.framework */; }; + D45480971A957465009D7229 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D45480981A957465009D7229 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45480961A957465009D7229 /* Result.swift */; }; + D45480991A9574B8009D7229 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D454806E1A9572F5009D7229 /* ResultTests.swift */; }; + D454809A1A9574BB009D7229 /* Result.h in Headers */ = {isa = PBXBuildFile; fileRef = D454805C1A9572F5009D7229 /* Result.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + D45480691A9572F5009D7229 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D45480561A9572F5009D7229; + remoteInfo = Result; + }; + D45480891A957362009D7229 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D454804E1A9572F5009D7229 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D454807C1A957361009D7229; + remoteInfo = "Result-iOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + BE740B551AEB28AB004B478F /* Box.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Box.framework; path = "../Carthage/Checkouts/Box/build/Debug-iphoneos/Box.framework"; sourceTree = ""; }; + D45480571A9572F5009D7229 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D454805B1A9572F5009D7229 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D454805C1A9572F5009D7229 /* Result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Result.h; sourceTree = ""; }; + D45480671A9572F5009D7229 /* Result-MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-MacTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D454806D1A9572F5009D7229 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D454806E1A9572F5009D7229 /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = ""; }; + D454807D1A957361009D7229 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480871A957362009D7229 /* Result-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Result-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + D45480961A957465009D7229 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D45480531A9572F5009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BE740B571AEB29F7004B478F /* Box.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480641A9572F5009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480681A9572F5009D7229 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480791A957361009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BE740B561AEB28AB004B478F /* Box.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480841A957362009D7229 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480881A957362009D7229 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D454804D1A9572F5009D7229 = { + isa = PBXGroup; + children = ( + D45480591A9572F5009D7229 /* Result */, + D454806B1A9572F5009D7229 /* ResultTests */, + D45480581A9572F5009D7229 /* Products */, + ); + sourceTree = ""; + usesTabs = 1; + }; + D45480581A9572F5009D7229 /* Products */ = { + isa = PBXGroup; + children = ( + D45480571A9572F5009D7229 /* Result.framework */, + D45480671A9572F5009D7229 /* Result-MacTests.xctest */, + D454807D1A957361009D7229 /* Result.framework */, + D45480871A957362009D7229 /* Result-iOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + D45480591A9572F5009D7229 /* Result */ = { + isa = PBXGroup; + children = ( + D454805C1A9572F5009D7229 /* Result.h */, + D45480961A957465009D7229 /* Result.swift */, + D454805A1A9572F5009D7229 /* Supporting Files */, + ); + path = Result; + sourceTree = ""; + }; + D454805A1A9572F5009D7229 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + BE740B551AEB28AB004B478F /* Box.framework */, + D454805B1A9572F5009D7229 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D454806B1A9572F5009D7229 /* ResultTests */ = { + isa = PBXGroup; + children = ( + D454806E1A9572F5009D7229 /* ResultTests.swift */, + D454806C1A9572F5009D7229 /* Supporting Files */, + ); + path = ResultTests; + sourceTree = ""; + }; + D454806C1A9572F5009D7229 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D454806D1A9572F5009D7229 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D45480541A9572F5009D7229 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D454805D1A9572F5009D7229 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D454807A1A957361009D7229 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D454809A1A9574BB009D7229 /* Result.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D45480561A9572F5009D7229 /* Result-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480721A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-Mac" */; + buildPhases = ( + D45480521A9572F5009D7229 /* Sources */, + D45480531A9572F5009D7229 /* Frameworks */, + D45480541A9572F5009D7229 /* Headers */, + D45480551A9572F5009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-Mac"; + productName = Result; + productReference = D45480571A9572F5009D7229 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480661A9572F5009D7229 /* Result-MacTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480751A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-MacTests" */; + buildPhases = ( + D45480631A9572F5009D7229 /* Sources */, + D45480641A9572F5009D7229 /* Frameworks */, + D45480651A9572F5009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D454806A1A9572F5009D7229 /* PBXTargetDependency */, + ); + name = "Result-MacTests"; + productName = ResultTests; + productReference = D45480671A9572F5009D7229 /* Result-MacTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D454807C1A957361009D7229 /* Result-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480941A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOS" */; + buildPhases = ( + D45480781A957361009D7229 /* Sources */, + D45480791A957361009D7229 /* Frameworks */, + D454807A1A957361009D7229 /* Headers */, + D454807B1A957361009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Result-iOS"; + productName = "Result-iOS"; + productReference = D454807D1A957361009D7229 /* Result.framework */; + productType = "com.apple.product-type.framework"; + }; + D45480861A957362009D7229 /* Result-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D45480951A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOSTests" */; + buildPhases = ( + D45480831A957362009D7229 /* Sources */, + D45480841A957362009D7229 /* Frameworks */, + D45480851A957362009D7229 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D454808A1A957362009D7229 /* PBXTargetDependency */, + ); + name = "Result-iOSTests"; + productName = "Result-iOSTests"; + productReference = D45480871A957362009D7229 /* Result-iOSTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D454804E1A9572F5009D7229 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Rob Rix"; + TargetAttributes = { + D45480561A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + }; + D45480661A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + }; + D454807C1A957361009D7229 = { + CreatedOnToolsVersion = 6.3; + }; + D45480861A957362009D7229 = { + CreatedOnToolsVersion = 6.3; + }; + }; + }; + buildConfigurationList = D45480511A9572F5009D7229 /* Build configuration list for PBXProject "Result" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D454804D1A9572F5009D7229; + productRefGroup = D45480581A9572F5009D7229 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D45480561A9572F5009D7229 /* Result-Mac */, + D45480661A9572F5009D7229 /* Result-MacTests */, + D454807C1A957361009D7229 /* Result-iOS */, + D45480861A957362009D7229 /* Result-iOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D45480551A9572F5009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480651A9572F5009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D454807B1A957361009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480851A957362009D7229 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D45480521A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480971A957465009D7229 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480631A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480781A957361009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480981A957465009D7229 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480831A957362009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480991A9574B8009D7229 /* ResultTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + D454806A1A9572F5009D7229 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D45480561A9572F5009D7229 /* Result-Mac */; + targetProxy = D45480691A9572F5009D7229 /* PBXContainerItemProxy */; + }; + D454808A1A957362009D7229 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D454807C1A957361009D7229 /* Result-iOS */; + targetProxy = D45480891A957362009D7229 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + D45480701A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + D45480711A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D45480731A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VALID_ARCHS = x86_64; + }; + name = Debug; + }; + D45480741A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SKIP_INSTALL = YES; + VALID_ARCHS = x86_64; + }; + name = Release; + }; + D45480761A9572F5009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D45480771A9572F5009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(DEVELOPER_FRAMEWORKS_DIR)", + "$(inherited)", + ); + INFOPLIST_FILE = ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + D45480901A957362009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D45480911A957362009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Result/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = Result; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D45480921A957362009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + }; + name = Debug; + }; + D45480931A957362009D7229 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = ResultTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D45480511A9572F5009D7229 /* Build configuration list for PBXProject "Result" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480701A9572F5009D7229 /* Debug */, + D45480711A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480721A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480731A9572F5009D7229 /* Debug */, + D45480741A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480751A9572F5009D7229 /* Build configuration list for PBXNativeTarget "Result-MacTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480761A9572F5009D7229 /* Debug */, + D45480771A9572F5009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480941A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480901A957362009D7229 /* Debug */, + D45480911A957362009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D45480951A957362009D7229 /* Build configuration list for PBXNativeTarget "Result-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D45480921A957362009D7229 /* Debug */, + D45480931A957362009D7229 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D454804E1A9572F5009D7229 /* Project object */; +} diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme new file mode 100644 index 0000000..b5e5ab2 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme new file mode 100644 index 0000000..8ff1a0f --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Result/Result/Info.plist b/Carthage/Checkouts/Result/Result/Info.plist new file mode 100644 index 0000000..0c9a82d --- /dev/null +++ b/Carthage/Checkouts/Result/Result/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.antitypical.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.0.1 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 Rob Rix. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Result/Result/Result.h b/Carthage/Checkouts/Result/Result/Result.h new file mode 100644 index 0000000..4742701 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/Result.h @@ -0,0 +1,8 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// Project version number for Result. +extern double ResultVersionNumber; + +/// Project version string for Result. +extern const unsigned char ResultVersionString[]; + diff --git a/Carthage/Checkouts/Result/Result/Result.swift b/Carthage/Checkouts/Result/Result/Result.swift new file mode 100644 index 0000000..1aeb1d8 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/Result.swift @@ -0,0 +1,201 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// An enum representing either a failure with an explanatory error, or a success with a result value. +public enum Result: Printable, DebugPrintable { + case Success(Box) + case Failure(Box) + + // MARK: Constructors + + /// Constructs a success wrapping a `value`. + public init(value: T) { + self = .Success(Box(value)) + } + + /// Constructs a failure wrapping an `error`. + public init(error: Error) { + self = .Failure(Box(error)) + } + + /// Constructs a result from an Optional, failing with `Error` if `nil` + public init(_ value: T?, @autoclosure failWith: () -> Error) { + self = value.map { .success($0) } ?? .failure(failWith()) + } + + /// Constructs a success wrapping a `value`. + public static func success(value: T) -> Result { + return Result(value: value) + } + + /// Constructs a failure wrapping an `error`. + public static func failure(error: Error) -> Result { + return Result(error: error) + } + + + // MARK: Deconstruction + + /// Returns the value from `Success` Results, `nil` otherwise. + public var value: T? { + return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil }) + } + + /// Returns the error from `Failure` Results, `nil` otherwise. + public var error: Error? { + return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 }) + } + + /// Case analysis for Result. + /// + /// Returns the value produced by applying `ifFailure` to `Failure` Results, or `ifSuccess` to `Success` Results. + public func analysis(@noescape #ifSuccess: T -> Result, @noescape ifFailure: Error -> Result) -> Result { + switch self { + case let .Success(value): + return ifSuccess(value.value) + case let .Failure(value): + return ifFailure(value.value) + } + } + + + // MARK: Higher-order functions + + /// Returns a new Result by mapping `Success`es’ values using `transform`, or re-wrapping `Failure`s’ errors. + public func map(@noescape transform: T -> U) -> Result { + return flatMap { .success(transform($0)) } + } + + /// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. + public func flatMap(@noescape transform: T -> Result) -> Result { + return analysis( + ifSuccess: transform, + ifFailure: Result.failure) + } + + /// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??` + public func recover(@autoclosure value: () -> T) -> T { + return self.value ?? value() + } + + /// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??` + public func recoverWith(@autoclosure result: () -> Result) -> Result { + return analysis( + ifSuccess: { _ in self }, + ifFailure: { _ in result() }) + } + + + // MARK: Errors + + /// The domain for errors constructed by Result. + public static var errorDomain: String { return "com.antitypical.Result" } + + /// The userInfo key for source functions in errors constructed by Result. + public static var functionKey: String { return "\(errorDomain).function" } + + /// The userInfo key for source file paths in errors constructed by Result. + public static var fileKey: String { return "\(errorDomain).file" } + + /// The userInfo key for source file line numbers in errors constructed by Result. + public static var lineKey: String { return "\(errorDomain).line" } + + /// Constructs an error. + public static func error(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__) -> NSError { + return NSError(domain: "com.antitypical.Result", code: 0, userInfo: [ + functionKey: function, + fileKey: file, + lineKey: line, + ]) + } + + + // MARK: Printable + + public var description: String { + return analysis( + ifSuccess: { ".Success(\($0))" }, + ifFailure: { ".Failure(\($0))" }) + } + + + // MARK: DebugPrintable + + public var debugDescription: String { + return description + } +} + + +/// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal. +public func == (left: Result, right: Result) -> Bool { + if let left = left.value, right = right.value { + return left == right + } else if let left = left.error, right = right.error { + return left == right + } + return false +} + +/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values. +public func != (left: Result, right: Result) -> Bool { + return !(left == right) +} + + +/// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits. +public func ?? (left: Result, @autoclosure right: () -> T) -> T { + return left.recover(right()) +} + +/// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits. +public func ?? (left: Result, @autoclosure right: () -> Result) -> Result { + return left.recoverWith(right()) +} + + +// MARK: - Cocoa API conveniences + +/// Constructs a Result with the result of calling `try` with an error pointer. +/// +/// This is convenient for wrapping Cocoa API which returns an object or `nil` + an error, by reference. e.g.: +/// +/// Result.try { NSData(contentsOfURL: URL, options: .DataReadingMapped, error: $0) } +public func try(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, try: NSErrorPointer -> T?) -> Result { + var error: NSError? + return try(&error).map(Result.success) ?? Result.failure(error ?? Result.error(function: function, file: file, line: line)) +} + +/// Constructs a Result with the result of calling `try` with an error pointer. +/// +/// This is convenient for wrapping Cocoa API which returns a `Bool` + an error, by reference. e.g.: +/// +/// Result.try { NSFileManager.defaultManager().removeItemAtURL(URL, error: $0) } +public func try(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, try: NSErrorPointer -> Bool) -> Result<(), NSError> { + var error: NSError? + return try(&error) ? + .success(()) + : .failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line)) +} + + +// MARK: - Operators + +infix operator >>- { + // Left-associativity so that chaining works like you’d expect, and for consistency with Haskell, Runes, swiftz, etc. + associativity left + + // Higher precedence than function application, but lower than function composition. + precedence 150 +} + + +/// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. +/// +/// This is a synonym for `flatMap`. +public func >>- (result: Result, @noescape transform: T -> Result) -> Result { + return result.flatMap(transform) +} + + +import Box +import Foundation diff --git a/Carthage/Checkouts/Result/ResultTests/Info.plist b/Carthage/Checkouts/Result/ResultTests/Info.plist new file mode 100644 index 0000000..358bdf0 --- /dev/null +++ b/Carthage/Checkouts/Result/ResultTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.antitypical.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Result/ResultTests/ResultTests.swift b/Carthage/Checkouts/Result/ResultTests/ResultTests.swift new file mode 100644 index 0000000..d0cd7c3 --- /dev/null +++ b/Carthage/Checkouts/Result/ResultTests/ResultTests.swift @@ -0,0 +1,101 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +final class ResultTests: XCTestCase { + func testMapTransformsSuccesses() { + XCTAssertEqual(success.map(count) ?? 0, 7) + } + + func testMapRewrapsFailures() { + XCTAssertEqual(failure.map(count) ?? 0, 0) + } + + func testInitOptionalSuccess() { + XCTAssert(Result("success" as String?, failWith: error) == success) + } + + func testInitOptionalFailure() { + XCTAssert(Result(nil, failWith: error) == failure) + } + + + // MARK: Errors + + func testErrorsIncludeTheSourceFile() { + let file = __FILE__ + XCTAssertEqual(Result<(), NSError>.error().file ?? "", file) + } + + func testErrorsIncludeTheSourceLine() { + let (line, error) = (__LINE__, Result<(), NSError>.error()) + XCTAssertEqual(error.line ?? -1, line) + } + + func testErrorsIncludeTheCallingFunction() { + let function = __FUNCTION__ + XCTAssertEqual(Result<(), NSError>.error().function ?? "", function) + } + + + // MARK: Cocoa API idioms + + func testTryProducesFailuresForBooleanAPIWithErrorReturnedByReference() { + let result = try { attempt(true, succeed: false, error: $0) } + XCTAssertFalse(result ?? false) + XCTAssertNotNil(result.error) + } + + func testTryProducesFailuresForOptionalWithErrorReturnedByReference() { + let result = try { attempt(1, succeed: false, error: $0) } + XCTAssertEqual(result ?? 0, 0) + XCTAssertNotNil(result.error) + } + + func testTryProducesSuccessesForBooleanAPI() { + let result = try { attempt(true, succeed: true, error: $0) } + XCTAssertTrue(result ?? false) + XCTAssertNil(result.error) + } + + func testTryProducesSuccessesForOptionalAPI() { + let result = try { attempt(1, succeed: true, error: $0) } + XCTAssertEqual(result ?? 0, 1) + XCTAssertNil(result.error) + } +} + + +// MARK: - Fixtures + +let success = Result.success("success") +let error = NSError(domain: "com.antitypical.Result", code: 0xdeadbeef, userInfo: nil) +let failure = Result.failure(error) + + +// MARK: - Helpers + +func attempt(value: T, #succeed: Bool, #error: NSErrorPointer) -> T? { + if succeed { + return value + } else { + error.memory = Result<(), NSError>.error() + return nil + } +} + +extension NSError { + var function: String? { + return userInfo?[Result<(), NSError>.functionKey as NSString] as? String + } + + var file: String? { + return userInfo?[Result<(), NSError>.fileKey as NSString] as? String + } + + var line: Int? { + return userInfo?[Result<(), NSError>.lineKey as NSString] as? Int + } +} + + +import Result +import XCTest diff --git a/Future.podspec b/Future.podspec new file mode 100644 index 0000000..6deafdc --- /dev/null +++ b/Future.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = "Future" + s.version = "0.0.1" + s.summary = "Swift µframework providing Future." + s.homepage = "https://github.com/nghialv/Future" + s.license = { :type => "MIT", :file => "LICENSE" } + s.author = { "nghialv" => "nghialv2607@gmail.com" } + s.social_media_url = "http://twitter.com/nghialv" + + s.platform = :ios + s.ios.deployment_target = "8.0" + s.source = { :git => "https://github.com/nghialv/Future.git", :tag => "0.0.1" } + s.source_files = "Future/*.swift" + s.requires_arc = true + s.dependency "Result", "0.4.3" +end diff --git a/Future.xcodeproj/project.pbxproj b/Future.xcodeproj/project.pbxproj new file mode 100644 index 0000000..3af2cac --- /dev/null +++ b/Future.xcodeproj/project.pbxproj @@ -0,0 +1,488 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8C1D912F1B1C2C090074458B /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C3904A31B1AF19800E4A444 /* Box.framework */; }; + 8C1D91301B1C2C090074458B /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C3904A41B1AF19800E4A444 /* Result.framework */; }; + 8C1D91331B1C30B40074458B /* FutureFunctionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C1D91321B1C30B40074458B /* FutureFunctionalTests.swift */; }; + 8C1D91351B1C3EDA0074458B /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C1D91341B1C3EDA0074458B /* TestUtils.swift */; }; + 8C3904A51B1AF19800E4A444 /* Box.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C3904A31B1AF19800E4A444 /* Box.framework */; }; + 8C3904A61B1AF19800E4A444 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C3904A41B1AF19800E4A444 /* Result.framework */; }; + 8C3904A91B1AF20700E4A444 /* Future.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C3904A81B1AF20700E4A444 /* Future.swift */; }; + 8C977AE31B1AF0B900047BF7 /* Future.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C977AE21B1AF0B900047BF7 /* Future.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8C977AE91B1AF0B900047BF7 /* Future.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C977ADD1B1AF0B900047BF7 /* Future.framework */; }; + 8C977AF01B1AF0B900047BF7 /* FutureStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C977AEF1B1AF0B900047BF7 /* FutureStateTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 8C977AEA1B1AF0B900047BF7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8C977AD41B1AF0B900047BF7 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8C977ADC1B1AF0B900047BF7; + remoteInfo = Future; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 8C1D91321B1C30B40074458B /* FutureFunctionalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FutureFunctionalTests.swift; sourceTree = ""; }; + 8C1D91341B1C3EDA0074458B /* TestUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = ""; }; + 8C3904A31B1AF19800E4A444 /* Box.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Box.framework; path = Carthage/Build/iOS/Box.framework; sourceTree = ""; }; + 8C3904A41B1AF19800E4A444 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = Carthage/Build/iOS/Result.framework; sourceTree = ""; }; + 8C3904A81B1AF20700E4A444 /* Future.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Future.swift; sourceTree = ""; }; + 8C977ADD1B1AF0B900047BF7 /* Future.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Future.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C977AE11B1AF0B900047BF7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8C977AE21B1AF0B900047BF7 /* Future.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Future.h; sourceTree = ""; }; + 8C977AE81B1AF0B900047BF7 /* FutureTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FutureTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C977AEE1B1AF0B900047BF7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8C977AEF1B1AF0B900047BF7 /* FutureStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FutureStateTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8C977AD91B1AF0B900047BF7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C3904A51B1AF19800E4A444 /* Box.framework in Frameworks */, + 8C3904A61B1AF19800E4A444 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8C977AE51B1AF0B900047BF7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C1D912F1B1C2C090074458B /* Box.framework in Frameworks */, + 8C1D91301B1C2C090074458B /* Result.framework in Frameworks */, + 8C977AE91B1AF0B900047BF7 /* Future.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8C977AD31B1AF0B900047BF7 = { + isa = PBXGroup; + children = ( + 8C977ADF1B1AF0B900047BF7 /* Future */, + 8C3904A31B1AF19800E4A444 /* Box.framework */, + 8C3904A41B1AF19800E4A444 /* Result.framework */, + 8C977AEC1B1AF0B900047BF7 /* FutureTests */, + 8C977ADE1B1AF0B900047BF7 /* Products */, + ); + sourceTree = ""; + }; + 8C977ADE1B1AF0B900047BF7 /* Products */ = { + isa = PBXGroup; + children = ( + 8C977ADD1B1AF0B900047BF7 /* Future.framework */, + 8C977AE81B1AF0B900047BF7 /* FutureTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 8C977ADF1B1AF0B900047BF7 /* Future */ = { + isa = PBXGroup; + children = ( + 8C977AE21B1AF0B900047BF7 /* Future.h */, + 8C3904A81B1AF20700E4A444 /* Future.swift */, + 8C977AE01B1AF0B900047BF7 /* Supporting Files */, + ); + path = Future; + sourceTree = ""; + }; + 8C977AE01B1AF0B900047BF7 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8C977AE11B1AF0B900047BF7 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 8C977AEC1B1AF0B900047BF7 /* FutureTests */ = { + isa = PBXGroup; + children = ( + 8C977AEF1B1AF0B900047BF7 /* FutureStateTests.swift */, + 8C1D91321B1C30B40074458B /* FutureFunctionalTests.swift */, + 8C1D91341B1C3EDA0074458B /* TestUtils.swift */, + 8C977AED1B1AF0B900047BF7 /* Supporting Files */, + ); + path = FutureTests; + sourceTree = ""; + }; + 8C977AED1B1AF0B900047BF7 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8C977AEE1B1AF0B900047BF7 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8C977ADA1B1AF0B900047BF7 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C977AE31B1AF0B900047BF7 /* Future.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 8C977ADC1B1AF0B900047BF7 /* Future */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8C977AF31B1AF0B900047BF7 /* Build configuration list for PBXNativeTarget "Future" */; + buildPhases = ( + 8C977AD81B1AF0B900047BF7 /* Sources */, + 8C977AD91B1AF0B900047BF7 /* Frameworks */, + 8C977ADA1B1AF0B900047BF7 /* Headers */, + 8C977ADB1B1AF0B900047BF7 /* Resources */, + 8C3904A71B1AF1AA00E4A444 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Future; + productName = Future; + productReference = 8C977ADD1B1AF0B900047BF7 /* Future.framework */; + productType = "com.apple.product-type.framework"; + }; + 8C977AE71B1AF0B900047BF7 /* FutureTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8C977AF61B1AF0B900047BF7 /* Build configuration list for PBXNativeTarget "FutureTests" */; + buildPhases = ( + 8C977AE41B1AF0B900047BF7 /* Sources */, + 8C977AE51B1AF0B900047BF7 /* Frameworks */, + 8C977AE61B1AF0B900047BF7 /* Resources */, + 8C1D91311B1C2DF40074458B /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 8C977AEB1B1AF0B900047BF7 /* PBXTargetDependency */, + ); + name = FutureTests; + productName = FutureTests; + productReference = 8C977AE81B1AF0B900047BF7 /* FutureTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8C977AD41B1AF0B900047BF7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Le VanNghia"; + TargetAttributes = { + 8C977ADC1B1AF0B900047BF7 = { + CreatedOnToolsVersion = 6.3.2; + }; + 8C977AE71B1AF0B900047BF7 = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 8C977AD71B1AF0B900047BF7 /* Build configuration list for PBXProject "Future" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8C977AD31B1AF0B900047BF7; + productRefGroup = 8C977ADE1B1AF0B900047BF7 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8C977ADC1B1AF0B900047BF7 /* Future */, + 8C977AE71B1AF0B900047BF7 /* FutureTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8C977ADB1B1AF0B900047BF7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8C977AE61B1AF0B900047BF7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 8C1D91311B1C2DF40074458B /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/Carthage/Build/iOS/Box.framework", + "$(SRCROOT)/Carthage/Build/iOS/Result.framework", + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/usr/local/bin/carthage copy-frameworks"; + }; + 8C3904A71B1AF1AA00E4A444 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/Carthage/Build/iOS/Box.framework", + "$(SRCROOT)/Carthage/Build/iOS/Result.framework", + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/usr/local/bin/carthage copy-frameworks"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8C977AD81B1AF0B900047BF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C3904A91B1AF20700E4A444 /* Future.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8C977AE41B1AF0B900047BF7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C977AF01B1AF0B900047BF7 /* FutureStateTests.swift in Sources */, + 8C1D91351B1C3EDA0074458B /* TestUtils.swift in Sources */, + 8C1D91331B1C30B40074458B /* FutureFunctionalTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 8C977AEB1B1AF0B900047BF7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8C977ADC1B1AF0B900047BF7 /* Future */; + targetProxy = 8C977AEA1B1AF0B900047BF7 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 8C977AF11B1AF0B900047BF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8C977AF21B1AF0B900047BF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 8C977AF41B1AF0B900047BF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Future/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 8C977AF51B1AF0B900047BF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Future/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 8C977AF71B1AF0B900047BF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = FutureTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 8C977AF81B1AF0B900047BF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = FutureTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8C977AD71B1AF0B900047BF7 /* Build configuration list for PBXProject "Future" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C977AF11B1AF0B900047BF7 /* Debug */, + 8C977AF21B1AF0B900047BF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8C977AF31B1AF0B900047BF7 /* Build configuration list for PBXNativeTarget "Future" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C977AF41B1AF0B900047BF7 /* Debug */, + 8C977AF51B1AF0B900047BF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8C977AF61B1AF0B900047BF7 /* Build configuration list for PBXNativeTarget "FutureTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C977AF71B1AF0B900047BF7 /* Debug */, + 8C977AF81B1AF0B900047BF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8C977AD41B1AF0B900047BF7 /* Project object */; +} diff --git a/Future/Future.h b/Future/Future.h new file mode 100644 index 0000000..aa5c00d --- /dev/null +++ b/Future/Future.h @@ -0,0 +1,19 @@ +// +// Future.h +// Future +// +// Created by Le VanNghia on 5/31/15. +// Copyright (c) 2015 Le VanNghia. All rights reserved. +// + +#import + +//! Project version number for Future. +FOUNDATION_EXPORT double FutureVersionNumber; + +//! Project version string for Future. +FOUNDATION_EXPORT const unsigned char FutureVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/Future/Future.swift b/Future/Future.swift new file mode 100644 index 0000000..a058c60 --- /dev/null +++ b/Future/Future.swift @@ -0,0 +1,245 @@ +// +// Future.swift +// Future +// +// Created by Le Van Nghia on 5/31/15. +// Copyright (c) 2015 Le Van Nghia. All rights reserved. +// + +import Foundation +import Result + +public class Future { + public typealias ResultType = Result + + // MARK: Properties + internal var result: Optional + private let operation: (ResultType -> Void) -> Void + + public var value: Optional { + return result?.value + } + + public var error: Optional { + return result?.error + } + + public var isCompleted: Bool { + return result != nil + } + + public var isSuccess: Bool { + return result?.value != nil + } + + public var isFailure: Bool { + return result?.error != nil + } + + // MAKR: Initilizers + + // Init a future with the given asynchronous operation. + public init(operation: (ResultType -> Void) -> Void) { + self.operation = operation + } + + // Init a future with the given result (Result). + public convenience init(result: ResultType) { + self.init(operation: { completion in + completion(result) + }) + } + + // Init a future that succeeded with the given `value`. + public convenience init(value: T) { + self.init(result: Result(value: value)) + } + + // Init a future that failed with the given `error`. + public convenience init(error: Error) { + self.init(result: Result(error: error)) + } + + + // MARK - Completing + + // Completes the future with the given `completion` closure. + // If the future is already completed, this will be applied immediately. + public func onComplete(completion: ResultType -> Void) { + if result != nil { + completion(result!) + return + } + self.operation { [weak self] result in + self?.result = result + completion(result) + } + } + + // Completes the future with `Success` completion. + // If the future is already completed, this will be applied immediately. + // And the `completion` closure is only executed if the future success. + public func onSuccess(completion: T -> Void) { + onComplete { result in + switch result { + case .Success(let bv): completion(bv.value) + default: break + } + } + } + + // Compeltes the future with `Failure` completion. + // If the future is already completed, this will be applied immediately. + // And the `completion` colosure is only executed if the future fails. + public func onFailure(completion: Error -> Void) { + onComplete { result in + switch result { + case .Failure(let be): completion(be.value) + default: break + } + } + } +} + +// MARK: Funtional composition + +extension Future { + + // map | you can also use `<^>` operator + // Creates a new future by applying a function to the successful result of this future. + // If this future is completed with an error then the new future will also contain this error. + public func map(f: T -> U) -> Future { + return Future(operation: { completion in + self.onComplete { result in + switch result { + case .Success(let bv): completion(Result(value: f(bv.value))) + case .Failure(let be): completion(Result(error: be.value)) + } + } + }) + } + + // flatMap | | you can also use `>>-` operator + // Creates a new future by applying a function to the successful result of this future, + // and returns the result of the function as the new future. + // If this future is completed with an error then the new future will also contain this error. + public func flatMap(f: T -> Future) -> Future { + return flatten(map(f)) + } + + // filter + // Creates a new future by filtering the value of the current future with a predicate. + // If the current future contains a value which satisfies the predicate, the new future will also hold that value. + // Otherwise, the resulting future will fail with `noSuchElementError`. + public func filter(noSuchElementError: Error, p: T -> Bool) -> Future { + return Future(operation: { completion in + self.onComplete { result in + switch result { + case .Success(let bv): + let r = p(bv.value) ? Result(value: bv.value) : Result(error: noSuchElementError) + completion(r) + case .Failure: completion(result) + } + } + }) + } + + // zip + // Creates a new future that holds the tupple of results of `this` and `that`. + public func zip(that: Future) -> Future<(T,U), Error> { + return self.flatMap { thisVal -> Future<(T,U), Error> in + return that.map { thatVal in + return (thisVal, thatVal) + } + } + } + + // recover + // Returns a future that succeeded if this is a success. + // Returns a future that succeeded by applying function `f` to `error` value if this is a failure. + public func recover(f: Error -> T) -> Future { + return Future(operation: { completion in + self.onComplete { result in + switch result { + case .Success: completion(result) + case .Failure(let be): completion(Result(value: f(be.value))) + } + } + }) + } + + // andThen + // Applies the side-effect function to the result of this future. + // and returns a new future with the result of this future. + public func andThen(result: Result -> Void) -> Future { + return Future(operation: { completion in + self.onComplete { r in + result(r) + completion(r) + } + }) + } +} + +// MARK: Funtions + +// flatten +public func flatten(future: Future, Error>) -> Future { + return Future(operation: { completion in + future.onComplete { result in + switch result { + case .Success(let bf): bf.value.onComplete(completion) + case .Failure(let be): completion(Result(error: be.value)) + } + } + }) +} + +// MARK: Printable + +extension Future: Printable { + public var description: String { + return "result: \(result)\n" + + "isCompleted: \(isCompleted)\n" + + "isSuccess: \(isSuccess)\n" + + "isFailure: \(isFailure)\n" + } +} + + +// MARK: DebugPrintable + +extension Future: DebugPrintable { + public var debugDescription: String { + return description + } +} + + +// MARK: Operators + +infix operator <^> { + // Left associativity + associativity left + + // Using the same `precedence` value with Swiftz's operator + precedence 140 +} + +infix operator >>- { + // Left associativity + associativity left + + // Using the same `precedence` value with Swiftz's operator + precedence 140 +} + +// Operator for `map` +public func <^> (future: Future, transform: T -> U) -> Future { + return future.map(transform) +} + +// Operator for `flatMap` +public func >>- (future: Future, transform: T -> Future) -> Future { + return future.flatMap(transform) +} \ No newline at end of file diff --git a/Future/Info.plist b/Future/Info.plist new file mode 100644 index 0000000..384d8fb --- /dev/null +++ b/Future/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.nghialv.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/FutureTests/FutureFunctionalTests.swift b/FutureTests/FutureFunctionalTests.swift new file mode 100644 index 0000000..c528751 --- /dev/null +++ b/FutureTests/FutureFunctionalTests.swift @@ -0,0 +1,160 @@ +// +// FutureFunctionalTests.swift +// Future +// +// Created by Le VanNghia on 6/1/15. +// Copyright (c) 2015 Le VanNghia. All rights reserved. +// + + +import UIKit +import XCTest +import Result +import Future + +class FutureFunctionalTests: XCTestCase { + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } +} + +extension FutureFunctionalTests { + func testMap() { + let f = requestString("12345") <^> { count($0) } + checkFutureShouldNotBeCompleted(f) + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, 5, "Future should return 5") + case .Failure(let be): XCTAssertFalse(true, "Future should not be failed") + } + } + + let f2 = f <^> { "\($0)" } + checkFutureShouldNotBeCompleted(f2) + f2.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, "5", "Future should return 5 as a String") + case .Failure(let be): XCTAssertFalse(true, "Future should not be failed") + } + } + } + + func testFlatMap() { + let f = requestString("12345") + .flatMap(requestStringLenght) + + checkFutureShouldNotBeCompleted(f) + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, 5, "Future should return 5") + case .Failure(let be): XCTAssertFalse(true, "Future should not be failed") + } + } + } + + func testFlatMapAndMap() { + let f = requestString("12345") + .map { count($0) } + .flatMap(requestStringFromNumber) + + checkFutureShouldNotBeCompleted(f) + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, "5", "Future should return 5 as a String") + case .Failure(let be): XCTAssertFalse(true, "Future should not be failed") + } + } + } + + func testFilter() { + let noSuchElementError = NSError(domain: "noSuchElement", code: 1, userInfo: nil) + + let f = requestString("12345") + .filter(noSuchElementError) { count($0) > 2 } + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, "12345", "Future should return 12345 as a String") + case .Failure(let be): XCTAssertFalse(true, "Future should not be failed") + } + } + } + + func testFilterWhenPredicateIsSatisfied() { + let noSuchElementError = NSError(domain: "noSuchElement", code: 1, userInfo: nil) + + let f = requestString("12345") + .filter(noSuchElementError) { count($0) > 5 } + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertNil(bv.value, "Future should return nil") + case .Failure(let be): XCTAssertEqual(be.value, noSuchElementError, "Future should return noSuchElement error") + } + } + } + + func testAndThen() { + var sideeffect = 0 + + let f = requestString("12345") + .andThen { sideeffect = count($0.value!) } + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, "12345", "Future should return 12345 as a String") + case .Failure(let be): XCTAssertFalse(true, "Future should not return an error") + } + XCTAssertEqual(sideeffect, 5, "SideEffect value should equal to 5") + } + } + + func testAndThenCombineWithFlatMap() { + var sideeffect = 0 + let f = requestString("12345") + .andThen { sideeffect = count($0.value!) } + .flatMap(requestStringLenght) + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, 5, "Future should return 5") + case .Failure(let be): XCTAssertFalse(true, "Future should not return an error") + } + XCTAssertEqual(sideeffect, 5, "SideEffect value should equal to 5") + } + } + + func testRecover() { + let f = requestStringReturnError("error message") + .recover { _ in "OK" } + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, "OK", "Future should return OK") + case .Failure(let be): XCTAssertFalse(true, "Future should not return an error") + } + } + } + + func testZip() { + let f1 = requestString("12345") + let f2 = requestStringFromNumber(1) + + let f = f1.zip(f2) + f.onComplete { result in + switch result { + case .Success(let bv): + XCTAssertEqual(bv.value.0, "12345", "Future should return tupple of 12345, 1") + XCTAssertEqual(bv.value.1, "1", "Future should return tupple of 12345, 1") + case .Failure(let be): XCTAssertFalse(true, "Future should not return an error") + } + } + } +} \ No newline at end of file diff --git a/FutureTests/FutureStateTests.swift b/FutureTests/FutureStateTests.swift new file mode 100644 index 0000000..63e0bbe --- /dev/null +++ b/FutureTests/FutureStateTests.swift @@ -0,0 +1,98 @@ +// +// FutureStateTests.swift +// FutureStateTests +// +// Created by Le VanNghia on 5/31/15. +// Copyright (c) 2015 Le VanNghia. All rights reserved. +// + +import UIKit +import XCTest +import Result +import Future + +class FutureStateTests: XCTestCase { + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } +} + +// MAKR: Test future state + +extension FutureStateTests { + func testFutureStateBeforeCompleting() { + let f1 = Future(value: 1) + let f2 = Future(error: NSError(domain: "Failed", code: 1, userInfo: nil)) + let f3 = Future { completion in + delay(2) { + completion(Result(value: 1)) + } + } + let futures = [f1, f2, f3] + for f in futures { + checkFutureShouldNotBeCompleted(f) + XCTAssertNil(f.value, "Future should return nil value") + XCTAssertNil(f.error, "Future should return nil error") + } + } + + func testFutureStateAfterCompletingForSucceededFuture() { + let f = Future(value: 1) + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, 1, "Future should return 1 in success result") + case .Failure: XCTAssertFalse(true, "Future should complete with success result") + } + } + + checkFutureShouldCompletedWithValue(f) + XCTAssertNotNil(f.value, "Future should return a value") + XCTAssertNil(f.error, "Future should return nil error") + } + + func testFutureStateAfterCompletingForFailedFuture() { + let error = NSError(domain: "Failed", code: 1, userInfo: nil) + let f = Future(error: error) + f.onComplete { result in + switch result { + case .Success: XCTAssertFalse(true, "Future should complete with failure result") + case .Failure(let be): XCTAssertEqual(be.value, error, "Future should return 1 in success result") + } + } + + checkFutureShouldCompletedWithError(f) + XCTAssertNil(f.value, "Future should return nil value") + XCTAssertNotNil(f.error, "Future should return an error") + } + + func testFutureStateAfterCompletingForAsyncFuture() { + let f = Future { completion in + delay(3) { + completion(Result(value: 1)) + } + } + let expectation = expectationWithDescription("Future completed") + + f.onComplete { result in + switch result { + case .Success(let bv): XCTAssertEqual(bv.value, 1, "Future should return 1 in success result") + case .Failure: XCTAssertFalse(true, "Future should complete with success result") + } + expectation.fulfill() + } + + checkFutureShouldNotBeCompleted(f) + XCTAssertNil(f.value, "Future should return nil value") + XCTAssertNil(f.error, "Future should return nil error") + + waitForExpectationsWithTimeout(3.5) { _ in + checkFutureShouldCompletedWithValue(f) + XCTAssertEqual(f.value!, 1, "Future should return 1") + XCTAssertNil(f.error, "Future should return nil error") + } + } +} diff --git a/FutureTests/Info.plist b/FutureTests/Info.plist new file mode 100644 index 0000000..2eb27c5 --- /dev/null +++ b/FutureTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.nghialv.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/FutureTests/TestUtils.swift b/FutureTests/TestUtils.swift new file mode 100644 index 0000000..65670f4 --- /dev/null +++ b/FutureTests/TestUtils.swift @@ -0,0 +1,76 @@ +// +// TestUtils.swift +// Future +// +// Created by Le VanNghia on 6/1/15. +// Copyright (c) 2015 Le VanNghia. All rights reserved. +// + +import Foundation +import XCTest +import Future +import Result + +func requestString(string: String) -> Future { + return Future { completion in + delay(1) { + completion(Result(value: string)) + } + } +} + + +func requestStringReturnError(string: String) -> Future { + return Future { completion in + delay(1) { + let error = NSError(domain: string, code: 1, userInfo: nil) + completion(Result(error: error)) + } + } +} + + +func requestStringFromNumber(number: Int) -> Future { + return Future { completion in + delay(1) { + completion(Result(value: "\(number)")) + } + } +} + +func requestStringLenght(string: String) -> Future { + return Future { completion in + delay(1) { + completion(Result(value: count(string))) + } + } +} + +func delay(delay:Double, closure:()->()) { + dispatch_after( + dispatch_time( + DISPATCH_TIME_NOW, + Int64(delay * Double(NSEC_PER_SEC)) + ), + dispatch_get_main_queue(), closure) +} + +func checkFutureShouldCompletedWithValue(f: Future) { + XCTAssertTrue(f.isCompleted, "Future should be Completed") + XCTAssertTrue(f.isSuccess, "Future should be Success") + XCTAssertFalse(f.isFailure, "Future should not be Failure") +} + +func checkFutureShouldCompletedWithError(f: Future) { + XCTAssertTrue(f.isCompleted, "Future should be Completed") + XCTAssertFalse(f.isSuccess, "Future should not be Success") + XCTAssertTrue(f.isFailure, "Future should be Failure") +} + +func checkFutureShouldNotBeCompleted(f: Future) { + XCTAssertFalse(f.isCompleted, "Future should not be Completed") + XCTAssertFalse(f.isSuccess, "Future should not be Success") + XCTAssertFalse(f.isFailure, "Future should not be Failure") + //XCTAssertNil(f.value, "Future should return nil value") + //XCTAssertNil(f.error, "Future should return nil error") +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8bc0cd3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Le Van Nghia + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7f09a79 --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +Future +===== + +[![Language](http://img.shields.io/badge/language-swift-brightgreen.svg?style=flat +)](https://developer.apple.com/swift) +[![CocoaPods](https://img.shields.io/cocoapods/v/Hakuba.svg)]() +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat +)](http://mit-license.org) +[![Issues](https://img.shields.io/github/issues/nghialv/Transporter.svg?style=flat +)](https://github.com/nghialv/Hakuba/issues?state=open) + + +Swift µframework providing Future<T, Error>. + +This library is inspired by the [talk of Javier Soto](https://realm.io/news/swift-summit-javier-soto-futures/) at SwiftSubmit2015 and the `Future` implementation in Scala. + +And this is using `antitypical/Result`. + +### Why we need Future? + +##### Traditional async code + +``` swift + func requestRepository(repoId: Int64, completion: (Repository?, NSError?) -> Void) {} + func requestUser(userId: Int64, completion: (User?, NSError?) -> Void) {} + + + // get owner info of a given repository + requestRepository(12345) { repo, error in + if let repo = repo { + requestUser(repo.ownerId) { user, error in + if let user = user { + // do something + } else { + // error handling + } + } + } else { + // error handling + } + } + +``` + +##### Code with Future + +``` swift +let future = requestRepository(12345) + .map { $0.ownerId } + .flatMap(requestUser) + +future.onCompleted { result in + switch result { + case .Success(let user): println(user) + case .Failure(let error): println(error) + } +} + +``` + +**Shorthand by using operator** + +``` swift +let future = requestRepository(12345) <^> { $0.ownerId } >>- requestUser + +future.onCompleted { result in + switch result { + case .Success(let user): println(user) + case .Failure(let error): println(error) + } +} +``` + +Usage +----- + +- `map` `<^>` +- `flatMap` `>>-` +- `filter` +- `andThen` +- `recover` +- `zip` +- `flatten` + + +Installation +----- + +- Using Carthage +> - Insert `github "nghialv/Future"` to your Cartfile +> - Run `carthage update` + + +- Using Cocoapods +> - Insert `pod "Future"` to you Podfile +> - Run `pod install` + +- Using Submodule + +Requirements +----- + +- Swift 1.2 (Xcode 6.3 or later) +- iOS 8.0 or later +