Swift: Initial creation of the Swift framework

Currently working (albeit without unit tests):
  - Getting the framework to dynamically link to the generated CGo lib for the simulator
  - Initializing the library and passing (limited) logging options
  - Basic logger in Swift, but doesn't redirect the VLogger into it
  - Creating handles back and forth to Go-owned objects
  - Vanadium's own Promise API
  - Creating contexts, async cancelling them, and setting deadlines
  - Async low-level RPC, but without any arguments or VOM-decoding/encoding
  - Rudimentary support for Vanadium errors, although the main bits will need to come from VDL
    generated code.

Change-Id: I52cc9a9699ed6e56924978d0616f14e8505d36c9
diff --git a/.gitignore b/.gitignore
index 1f8d8c1..691869c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,34 @@
-/.jiri
\ No newline at end of file
+/.jiri
+
+# Don't include any generated content from CGo
+lib/v23/x
+
+# Xcode
+#
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+## Build generated
+build/
+DerivedData
+
+## Various settings
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+
+## Other
+*.xccheckout
+*.moved-aside
+*.xcuserstate
+*.xcscmblueprint
+
+## Obj-C/Swift specific
+*.hmap
+*.ipa
+
diff --git a/clang/clangwrap++.sh b/clang/clangwrap++.sh
new file mode 100755
index 0000000..a52d1ff
--- /dev/null
+++ b/clang/clangwrap++.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+# This uses the latest available iOS SDK, which is recommended.
+# To select a specific SDK, run 'xcodebuild -showsdks'
+# to see the available SDKs and replace iphoneos with one of them.
+if [ "$GOARCH" == "arm" ] || [ "$GOARCH" == "arm64" ]; then
+  echo "Building for iPhone OS"
+  SDK=iphoneos
+else
+  echo "Building for iPhone Simulator"
+  SDK=iphonesimulator
+fi
+
+SDK_PATH=`xcrun --sdk $SDK --show-sdk-path`
+export IPHONEOS_DEPLOYMENT_TARGET=8.0
+# cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang.
+CLANG=`xcrun --sdk $SDK --find clang++`
+
+if [ "$GOARCH" == "arm" ]; then
+  CLANGARCH="armv7"
+elif [ "$GOARCH" == "arm64" ]; then
+  CLANGARCH="arm64"
+elif [ "$GOARCH" == "386" ]; then
+  CLANGARCH="i386"
+elif [ "$GOARCH" == "amd64" ]; then
+  CLANGARCH="x86_64"
+else
+  echo "unknown GOARCH=$GOARCH" >&2
+  exit 1
+fi
+
+exec $CLANG -arch $CLANGARCH -isysroot $SDK_PATH -fembed-bitcode "$@"
diff --git a/clang/clangwrap.sh b/clang/clangwrap.sh
new file mode 100755
index 0000000..e425907
--- /dev/null
+++ b/clang/clangwrap.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+# This uses the latest available iOS SDK, which is recommended.
+# To select a specific SDK, run 'xcodebuild -showsdks'
+# to see the available SDKs and replace iphoneos with one of them.
+if [ "$GOARCH" == "arm" ] || [ "$GOARCH" == "arm64" ]; then
+  echo "Building for iPhone OS"
+  SDK=iphoneos
+else
+  echo "Building for iPhone Simulator"
+  SDK=iphonesimulator
+fi
+
+SDK_PATH=`xcrun --sdk $SDK --show-sdk-path`
+export IPHONEOS_DEPLOYMENT_TARGET=8.0
+# cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang.
+CLANG=`xcrun --sdk $SDK --find clang`
+
+if [ "$GOARCH" == "arm" ]; then
+	CLANGARCH="armv7"
+elif [ "$GOARCH" == "arm64" ]; then
+	CLANGARCH="arm64"
+elif [ "$GOARCH" == "386" ]; then
+  CLANGARCH="i386"
+elif [ "$GOARCH" == "amd64" ]; then
+  CLANGARCH="x86_64"
+else
+	echo "unknown GOARCH=$GOARCH" >&2
+	exit 1
+fi
+
+exec $CLANG -arch $CLANGARCH -isysroot $SDK_PATH -fembed-bitcode "$@"
diff --git a/demo/Demo.xcodeproj/project.pbxproj b/demo/Demo.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..a7f9541
--- /dev/null
+++ b/demo/Demo.xcodeproj/project.pbxproj
@@ -0,0 +1,486 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		9306FB941BFC049400DE7190 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9306FB931BFC049400DE7190 /* AppDelegate.swift */; };
+		9306FB961BFC049400DE7190 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9306FB951BFC049400DE7190 /* ViewController.swift */; };
+		9306FB991BFC049400DE7190 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9306FB971BFC049400DE7190 /* Main.storyboard */; };
+		9306FB9B1BFC049400DE7190 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9306FB9A1BFC049400DE7190 /* Assets.xcassets */; };
+		9306FB9E1BFC049400DE7190 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9306FB9C1BFC049400DE7190 /* LaunchScreen.storyboard */; };
+		9306FBA91BFC049400DE7190 /* DemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9306FBA81BFC049400DE7190 /* DemoTests.swift */; };
+		9306FBBC1BFC04B900DE7190 /* v23.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9306FBB91BFC04AE00DE7190 /* v23.framework */; };
+		9306FBBD1BFC04B900DE7190 /* v23.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9306FBB91BFC04AE00DE7190 /* v23.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		9306FBA51BFC049400DE7190 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 9306FB881BFC049400DE7190 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 9306FB8F1BFC049400DE7190;
+			remoteInfo = Demo;
+		};
+		9306FBB81BFC04AE00DE7190 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 9306FBB31BFC04AE00DE7190 /* v23.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 939417061BF547AB00F3F996;
+			remoteInfo = v23;
+		};
+		9306FBBA1BFC04AE00DE7190 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 9306FBB31BFC04AE00DE7190 /* v23.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 939417101BF547AB00F3F996;
+			remoteInfo = v23Tests;
+		};
+		9306FBBE1BFC04B900DE7190 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 9306FBB31BFC04AE00DE7190 /* v23.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = 939417051BF547AB00F3F996;
+			remoteInfo = v23;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		9306FBC01BFC04B900DE7190 /* Embed Frameworks */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 10;
+			files = (
+				9306FBBD1BFC04B900DE7190 /* v23.framework in Embed Frameworks */,
+			);
+			name = "Embed Frameworks";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		9306FB901BFC049400DE7190 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		9306FB931BFC049400DE7190 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+		9306FB951BFC049400DE7190 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
+		9306FB981BFC049400DE7190 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+		9306FB9A1BFC049400DE7190 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		9306FB9D1BFC049400DE7190 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		9306FB9F1BFC049400DE7190 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		9306FBA41BFC049400DE7190 /* DemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		9306FBA81BFC049400DE7190 /* DemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoTests.swift; sourceTree = "<group>"; };
+		9306FBAA1BFC049400DE7190 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		9306FBB31BFC04AE00DE7190 /* v23.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = v23.xcodeproj; path = ../lib/v23.xcodeproj; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		9306FB8D1BFC049400DE7190 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9306FBBC1BFC04B900DE7190 /* v23.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9306FBA11BFC049400DE7190 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		9306FB871BFC049400DE7190 = {
+			isa = PBXGroup;
+			children = (
+				9306FBB31BFC04AE00DE7190 /* v23.xcodeproj */,
+				9306FB921BFC049400DE7190 /* Demo */,
+				9306FBA71BFC049400DE7190 /* DemoTests */,
+				9306FB911BFC049400DE7190 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		9306FB911BFC049400DE7190 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				9306FB901BFC049400DE7190 /* Demo.app */,
+				9306FBA41BFC049400DE7190 /* DemoTests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		9306FB921BFC049400DE7190 /* Demo */ = {
+			isa = PBXGroup;
+			children = (
+				9306FB931BFC049400DE7190 /* AppDelegate.swift */,
+				9306FB951BFC049400DE7190 /* ViewController.swift */,
+				9306FB971BFC049400DE7190 /* Main.storyboard */,
+				9306FB9A1BFC049400DE7190 /* Assets.xcassets */,
+				9306FB9C1BFC049400DE7190 /* LaunchScreen.storyboard */,
+				9306FB9F1BFC049400DE7190 /* Info.plist */,
+			);
+			path = Demo;
+			sourceTree = "<group>";
+		};
+		9306FBA71BFC049400DE7190 /* DemoTests */ = {
+			isa = PBXGroup;
+			children = (
+				9306FBA81BFC049400DE7190 /* DemoTests.swift */,
+				9306FBAA1BFC049400DE7190 /* Info.plist */,
+			);
+			path = DemoTests;
+			sourceTree = "<group>";
+		};
+		9306FBB41BFC04AE00DE7190 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				9306FBB91BFC04AE00DE7190 /* v23.framework */,
+				9306FBBB1BFC04AE00DE7190 /* v23Tests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		9306FB8F1BFC049400DE7190 /* Demo */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 9306FBAD1BFC049400DE7190 /* Build configuration list for PBXNativeTarget "Demo" */;
+			buildPhases = (
+				9306FB8C1BFC049400DE7190 /* Sources */,
+				9306FB8D1BFC049400DE7190 /* Frameworks */,
+				9306FB8E1BFC049400DE7190 /* Resources */,
+				9306FBC01BFC04B900DE7190 /* Embed Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				9306FBBF1BFC04B900DE7190 /* PBXTargetDependency */,
+			);
+			name = Demo;
+			productName = Demo;
+			productReference = 9306FB901BFC049400DE7190 /* Demo.app */;
+			productType = "com.apple.product-type.application";
+		};
+		9306FBA31BFC049400DE7190 /* DemoTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 9306FBB01BFC049400DE7190 /* Build configuration list for PBXNativeTarget "DemoTests" */;
+			buildPhases = (
+				9306FBA01BFC049400DE7190 /* Sources */,
+				9306FBA11BFC049400DE7190 /* Frameworks */,
+				9306FBA21BFC049400DE7190 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				9306FBA61BFC049400DE7190 /* PBXTargetDependency */,
+			);
+			name = DemoTests;
+			productName = DemoTests;
+			productReference = 9306FBA41BFC049400DE7190 /* DemoTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		9306FB881BFC049400DE7190 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0710;
+				LastUpgradeCheck = 0710;
+				ORGANIZATIONNAME = "Google Inc.";
+				TargetAttributes = {
+					9306FB8F1BFC049400DE7190 = {
+						CreatedOnToolsVersion = 7.1;
+					};
+					9306FBA31BFC049400DE7190 = {
+						CreatedOnToolsVersion = 7.1;
+						TestTargetID = 9306FB8F1BFC049400DE7190;
+					};
+				};
+			};
+			buildConfigurationList = 9306FB8B1BFC049400DE7190 /* Build configuration list for PBXProject "Demo" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 9306FB871BFC049400DE7190;
+			productRefGroup = 9306FB911BFC049400DE7190 /* Products */;
+			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = 9306FBB41BFC04AE00DE7190 /* Products */;
+					ProjectRef = 9306FBB31BFC04AE00DE7190 /* v23.xcodeproj */;
+				},
+			);
+			projectRoot = "";
+			targets = (
+				9306FB8F1BFC049400DE7190 /* Demo */,
+				9306FBA31BFC049400DE7190 /* DemoTests */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+		9306FBB91BFC04AE00DE7190 /* v23.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = v23.framework;
+			remoteRef = 9306FBB81BFC04AE00DE7190 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		9306FBBB1BFC04AE00DE7190 /* v23Tests.xctest */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.cfbundle;
+			path = v23Tests.xctest;
+			remoteRef = 9306FBBA1BFC04AE00DE7190 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+		9306FB8E1BFC049400DE7190 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9306FB9E1BFC049400DE7190 /* LaunchScreen.storyboard in Resources */,
+				9306FB9B1BFC049400DE7190 /* Assets.xcassets in Resources */,
+				9306FB991BFC049400DE7190 /* Main.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9306FBA21BFC049400DE7190 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		9306FB8C1BFC049400DE7190 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9306FB961BFC049400DE7190 /* ViewController.swift in Sources */,
+				9306FB941BFC049400DE7190 /* AppDelegate.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9306FBA01BFC049400DE7190 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9306FBA91BFC049400DE7190 /* DemoTests.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		9306FBA61BFC049400DE7190 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 9306FB8F1BFC049400DE7190 /* Demo */;
+			targetProxy = 9306FBA51BFC049400DE7190 /* PBXContainerItemProxy */;
+		};
+		9306FBBF1BFC04B900DE7190 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = v23;
+			targetProxy = 9306FBBE1BFC04B900DE7190 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+		9306FB971BFC049400DE7190 /* Main.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				9306FB981BFC049400DE7190 /* Base */,
+			);
+			name = Main.storyboard;
+			sourceTree = "<group>";
+		};
+		9306FB9C1BFC049400DE7190 /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				9306FB9D1BFC049400DE7190 /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		9306FBAB1BFC049400DE7190 /* 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;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = 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_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 = 9.1;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		9306FBAC1BFC049400DE7190 /* 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;
+				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 = 9.1;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		9306FBAE1BFC049400DE7190 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
+				INFOPLIST_FILE = Demo/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.Demo;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		9306FBAF1BFC049400DE7190 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
+				INFOPLIST_FILE = Demo/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.Demo;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+		9306FBB11BFC049400DE7190 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				INFOPLIST_FILE = DemoTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.DemoTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo";
+			};
+			name = Debug;
+		};
+		9306FBB21BFC049400DE7190 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				INFOPLIST_FILE = DemoTests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.DemoTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		9306FB8B1BFC049400DE7190 /* Build configuration list for PBXProject "Demo" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9306FBAB1BFC049400DE7190 /* Debug */,
+				9306FBAC1BFC049400DE7190 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		9306FBAD1BFC049400DE7190 /* Build configuration list for PBXNativeTarget "Demo" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9306FBAE1BFC049400DE7190 /* Debug */,
+				9306FBAF1BFC049400DE7190 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		9306FBB01BFC049400DE7190 /* Build configuration list for PBXNativeTarget "DemoTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9306FBB11BFC049400DE7190 /* Debug */,
+				9306FBB21BFC049400DE7190 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 9306FB881BFC049400DE7190 /* Project object */;
+}
diff --git a/demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..02a6973
--- /dev/null
+++ b/demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:Demo.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/demo/Demo/AppDelegate.swift b/demo/Demo/AppDelegate.swift
new file mode 100644
index 0000000..a53aa03
--- /dev/null
+++ b/demo/Demo/AppDelegate.swift
@@ -0,0 +1,42 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import UIKit
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+  var window: UIWindow?
+
+
+  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
+    // Override point for customization after application launch.
+    return true
+  }
+
+  func applicationWillResignActive(application: UIApplication) {
+    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+  }
+
+  func applicationDidEnterBackground(application: UIApplication) {
+    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+  }
+
+  func applicationWillEnterForeground(application: UIApplication) {
+    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+  }
+
+  func applicationDidBecomeActive(application: UIApplication) {
+    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+  }
+
+  func applicationWillTerminate(application: UIApplication) {
+    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+  }
+
+
+}
+
diff --git a/demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json b/demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..36d2c80
--- /dev/null
+++ b/demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "76x76",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "76x76",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demo/Demo/Base.lproj/LaunchScreen.storyboard b/demo/Demo/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..f70f059
--- /dev/null
+++ b/demo/Demo/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/demo/Demo/Base.lproj/Main.storyboard b/demo/Demo/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..3a2a49b
--- /dev/null
+++ b/demo/Demo/Base.lproj/Main.storyboard
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
+                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+        </scene>
+    </scenes>
+</document>
diff --git a/demo/Demo/Info.plist b/demo/Demo/Info.plist
new file mode 100644
index 0000000..40c6215
--- /dev/null
+++ b/demo/Demo/Info.plist
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIMainStoryboardFile</key>
+	<string>Main</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>
diff --git a/demo/Demo/ViewController.swift b/demo/Demo/ViewController.swift
new file mode 100644
index 0000000..6a95b67
--- /dev/null
+++ b/demo/Demo/ViewController.swift
@@ -0,0 +1,83 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import UIKit
+import v23
+
+class ViewController: UIViewController {
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    startVanadium()
+    testHelloCall()
+    testCancel()
+  }
+
+  override func didReceiveMemoryWarning() {
+    super.didReceiveMemoryWarning()
+  }
+
+  let addr = "/" + "@6@wsh@100.110.93.71:23000@@b6752aa9f33f86b9aecf25ecad73c8a4@l@tutorial@@"
+  var instance:V23? = nil
+
+  func startVanadium() {
+    do {
+      try v23.configure()
+      instance = v23.instance
+    } catch let e as VError {
+      print("Got a verror:", e)
+    } catch let e {
+      print("Got an exception:", e)
+    }
+  }
+  
+  func testHelloCall() {
+    var ctx = instance!.context
+    ctx.deadline = NSDate(timeIntervalSinceNow: 1)
+    print("Calling startCall")
+    
+    do {
+      let client = try ctx.client()
+      client.call(name: addr, method: "Get", args: nil, returnArgsLength: 1, skipServerAuth: true)
+        .onResolve { result -> () in
+          print("Finished with \(result)")
+        }
+        .onReject { err -> () in
+          print("Errored with \(err)")
+      }
+    } catch let e as VError {
+      print("Got a verror:", e)
+    } catch let e {
+      print("Got an exception:", e)
+    }
+  }
+
+  func testCancel() {
+    var ctx = instance!.context
+    ctx.isCancellable = true
+    print("Calling startCall")
+    
+    do {
+      let client = try ctx.client()
+      client.call(name: addr, method: "Get", args: nil, returnArgsLength: 1, skipServerAuth: true)
+        .onResolve { result -> () in
+          print("Call shouldnt have finished with \(result)")
+        }
+        .onReject { err -> () in
+          print("Call errored with \(err)")
+      }
+      try ctx.cancel()
+        .onResolve {
+          print("Cancelled correctly")
+        }
+        .onReject { err -> () in
+          print("Cancel errored with \(err)")
+        }
+    } catch let e as VError {
+      print("Got an unexpected verror:", e)
+    } catch let e {
+      print("Got an unexpected exception:", e)
+    }
+  }
+}
+
diff --git a/demo/DemoTests/DemoTests.swift b/demo/DemoTests/DemoTests.swift
new file mode 100644
index 0000000..fabf604
--- /dev/null
+++ b/demo/DemoTests/DemoTests.swift
@@ -0,0 +1,36 @@
+//
+//  DemoTests.swift
+//  DemoTests
+//
+//  Created by Aaron Zinman on 11/17/15.
+//  Copyright © 2015 Google Inc. All rights reserved.
+//
+
+import XCTest
+@testable import Demo
+
+class DemoTests: XCTestCase {
+    
+    override func setUp() {
+        super.setUp()
+        // Put setup code here. This method is called before the invocation of each test method in the class.
+    }
+    
+    override func tearDown() {
+        // Put teardown code here. This method is called after the invocation of each test method in the class.
+        super.tearDown()
+    }
+    
+    func testExample() {
+        // This is an example of a functional test case.
+        // Use XCTAssert and related functions to verify your tests produce the correct results.
+    }
+    
+    func testPerformanceExample() {
+        // This is an example of a performance test case.
+        self.measureBlock {
+            // Put the code you want to measure the time of here.
+        }
+    }
+    
+}
diff --git a/demo/DemoTests/Info.plist b/demo/DemoTests/Info.plist
new file mode 100644
index 0000000..ba72822
--- /dev/null
+++ b/demo/DemoTests/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/lib/v23.xcodeproj/project.pbxproj b/lib/v23.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..9cffdd4
--- /dev/null
+++ b/lib/v23.xcodeproj/project.pbxproj
@@ -0,0 +1,582 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		9306529E1BFD0E3F0093B650 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 9306529D1BFD0E3F0093B650 /* types.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		930652A11BFD236E0093B650 /* context.h in Headers */ = {isa = PBXBuildFile; fileRef = 930652A01BFD236E0093B650 /* context.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		930652A51BFD42BC0093B650 /* rpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 930652A41BFD42BC0093B650 /* rpc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		9306FB831BFC012500DE7190 /* rt.h in Headers */ = {isa = PBXBuildFile; fileRef = 9306FB801BFC012500DE7190 /* rt.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		9306FB841BFC012500DE7190 /* ios.h in Headers */ = {isa = PBXBuildFile; fileRef = 9306FB811BFC012500DE7190 /* ios.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		9306FB851BFC012500DE7190 /* v23.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9306FB821BFC012500DE7190 /* v23.dylib */; };
+		9306FB861BFC020A00DE7190 /* v23.dylib in Copy Files */ = {isa = PBXBuildFile; fileRef = 9306FB821BFC012500DE7190 /* v23.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		9394170A1BF547AB00F3F996 /* v23.h in Headers */ = {isa = PBXBuildFile; fileRef = 939417091BF547AB00F3F996 /* v23.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		939417111BF547AB00F3F996 /* v23.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 939417061BF547AB00F3F996 /* v23.framework */; };
+		939417161BF547AB00F3F996 /* v23Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 939417151BF547AB00F3F996 /* v23Tests.swift */; };
+		93B626511C0D5D3F00C5C1D0 /* PromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626501C0D5D3F00C5C1D0 /* PromiseTests.swift */; };
+		93B6266C1C0E598800C5C1D0 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B6265B1C0E598800C5C1D0 /* Errors.swift */; };
+		93B6266D1C0E598800C5C1D0 /* Refs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B6265C1C0E598800C5C1D0 /* Refs.swift */; };
+		93B6266E1C0E598800C5C1D0 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B6265D1C0E598800C5C1D0 /* Types.swift */; };
+		93B6266F1C0E598800C5C1D0 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B6265F1C0E598800C5C1D0 /* Context.swift */; };
+		93B626701C0E598800C5C1D0 /* RPC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626611C0E598800C5C1D0 /* RPC.swift */; };
+		93B626711C0E598800C5C1D0 /* Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626631C0E598800C5C1D0 /* Runtime.swift */; };
+		93B626721C0E598800C5C1D0 /* Security.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626641C0E598800C5C1D0 /* Security.swift */; };
+		93B626731C0E598800C5C1D0 /* Dates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626661C0E598800C5C1D0 /* Dates.swift */; };
+		93B626741C0E598800C5C1D0 /* Locking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626671C0E598800C5C1D0 /* Locking.swift */; };
+		93B626751C0E598800C5C1D0 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626681C0E598800C5C1D0 /* Logging.swift */; };
+		93B626761C0E598800C5C1D0 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B626691C0E598800C5C1D0 /* Promise.swift */; };
+		93B626771C0E598800C5C1D0 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B6266A1C0E598800C5C1D0 /* Strings.swift */; };
+		93B626781C0E598800C5C1D0 /* Threads.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93B6266B1C0E598800C5C1D0 /* Threads.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		939417121BF547AB00F3F996 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 939416FD1BF547AB00F3F996 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 939417051BF547AB00F3F996;
+			remoteInfo = v23;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		9306FB481BFAA66300DE7190 /* Copy Files */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 6;
+			files = (
+				9306FB861BFC020A00DE7190 /* v23.dylib in Copy Files */,
+			);
+			name = "Copy Files";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		9306529D1BFD0E3F0093B650 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
+		930652A01BFD236E0093B650 /* context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = context.h; sourceTree = "<group>"; };
+		930652A41BFD42BC0093B650 /* rpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpc.h; sourceTree = "<group>"; };
+		9306FB801BFC012500DE7190 /* rt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rt.h; sourceTree = "<group>"; };
+		9306FB811BFC012500DE7190 /* ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios.h; sourceTree = "<group>"; };
+		9306FB821BFC012500DE7190 /* v23.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = v23.dylib; sourceTree = "<group>"; };
+		939417061BF547AB00F3F996 /* v23.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = v23.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		939417091BF547AB00F3F996 /* v23.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = v23.h; sourceTree = "<group>"; };
+		9394170B1BF547AB00F3F996 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		939417101BF547AB00F3F996 /* v23Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = v23Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		939417151BF547AB00F3F996 /* v23Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = v23Tests.swift; sourceTree = "<group>"; };
+		939417171BF547AB00F3F996 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		93B626501C0D5D3F00C5C1D0 /* PromiseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseTests.swift; sourceTree = "<group>"; };
+		93B6265B1C0E598800C5C1D0 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
+		93B6265C1C0E598800C5C1D0 /* Refs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Refs.swift; sourceTree = "<group>"; };
+		93B6265D1C0E598800C5C1D0 /* Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; };
+		93B6265F1C0E598800C5C1D0 /* Context.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Context.swift; sourceTree = "<group>"; };
+		93B626611C0E598800C5C1D0 /* RPC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RPC.swift; sourceTree = "<group>"; };
+		93B626631C0E598800C5C1D0 /* Runtime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Runtime.swift; sourceTree = "<group>"; };
+		93B626641C0E598800C5C1D0 /* Security.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Security.swift; sourceTree = "<group>"; };
+		93B626661C0E598800C5C1D0 /* Dates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dates.swift; sourceTree = "<group>"; };
+		93B626671C0E598800C5C1D0 /* Locking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Locking.swift; sourceTree = "<group>"; };
+		93B626681C0E598800C5C1D0 /* Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
+		93B626691C0E598800C5C1D0 /* Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = "<group>"; };
+		93B6266A1C0E598800C5C1D0 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
+		93B6266B1C0E598800C5C1D0 /* Threads.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Threads.swift; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		939417021BF547AB00F3F996 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9306FB851BFC012500DE7190 /* v23.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9394170D1BF547AB00F3F996 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				939417111BF547AB00F3F996 /* v23.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		9306529F1BFD236E0093B650 /* v23 */ = {
+			isa = PBXGroup;
+			children = (
+				930652A01BFD236E0093B650 /* context.h */,
+			);
+			path = v23;
+			sourceTree = "<group>";
+		};
+		9306FB7C1BFC012500DE7190 /* x */ = {
+			isa = PBXGroup;
+			children = (
+				9306FB7D1BFC012500DE7190 /* ios */,
+				9306FB811BFC012500DE7190 /* ios.h */,
+				9306529D1BFD0E3F0093B650 /* types.h */,
+				9306FB821BFC012500DE7190 /* v23.dylib */,
+			);
+			path = x;
+			sourceTree = "<group>";
+		};
+		9306FB7D1BFC012500DE7190 /* ios */ = {
+			isa = PBXGroup;
+			children = (
+				9306529F1BFD236E0093B650 /* v23 */,
+				9306FB7E1BFC012500DE7190 /* impl */,
+			);
+			path = ios;
+			sourceTree = "<group>";
+		};
+		9306FB7E1BFC012500DE7190 /* impl */ = {
+			isa = PBXGroup;
+			children = (
+				9306FB7F1BFC012500DE7190 /* google */,
+			);
+			path = impl;
+			sourceTree = "<group>";
+		};
+		9306FB7F1BFC012500DE7190 /* google */ = {
+			isa = PBXGroup;
+			children = (
+				930652A41BFD42BC0093B650 /* rpc.h */,
+				9306FB801BFC012500DE7190 /* rt.h */,
+			);
+			path = google;
+			sourceTree = "<group>";
+		};
+		939416FC1BF547AB00F3F996 = {
+			isa = PBXGroup;
+			children = (
+				939417081BF547AB00F3F996 /* v23 */,
+				939417141BF547AB00F3F996 /* v23Tests */,
+				939417071BF547AB00F3F996 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		939417071BF547AB00F3F996 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				939417061BF547AB00F3F996 /* v23.framework */,
+				939417101BF547AB00F3F996 /* v23Tests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		939417081BF547AB00F3F996 /* v23 */ = {
+			isa = PBXGroup;
+			children = (
+				939417091BF547AB00F3F996 /* v23.h */,
+				9394170B1BF547AB00F3F996 /* Info.plist */,
+				93B6265A1C0E598800C5C1D0 /* bridge */,
+				93B6265E1C0E598800C5C1D0 /* context */,
+				93B626601C0E598800C5C1D0 /* rpc */,
+				93B626621C0E598800C5C1D0 /* rt */,
+				93B626651C0E598800C5C1D0 /* util */,
+				9306FB7C1BFC012500DE7190 /* x */,
+			);
+			path = v23;
+			sourceTree = "<group>";
+		};
+		939417141BF547AB00F3F996 /* v23Tests */ = {
+			isa = PBXGroup;
+			children = (
+				939417171BF547AB00F3F996 /* Info.plist */,
+				93B626501C0D5D3F00C5C1D0 /* PromiseTests.swift */,
+				939417151BF547AB00F3F996 /* v23Tests.swift */,
+			);
+			path = v23Tests;
+			sourceTree = "<group>";
+		};
+		93B6265A1C0E598800C5C1D0 /* bridge */ = {
+			isa = PBXGroup;
+			children = (
+				93B6265B1C0E598800C5C1D0 /* Errors.swift */,
+				93B6265C1C0E598800C5C1D0 /* Refs.swift */,
+				93B6265D1C0E598800C5C1D0 /* Types.swift */,
+			);
+			path = bridge;
+			sourceTree = "<group>";
+		};
+		93B6265E1C0E598800C5C1D0 /* context */ = {
+			isa = PBXGroup;
+			children = (
+				93B6265F1C0E598800C5C1D0 /* Context.swift */,
+			);
+			path = context;
+			sourceTree = "<group>";
+		};
+		93B626601C0E598800C5C1D0 /* rpc */ = {
+			isa = PBXGroup;
+			children = (
+				93B626611C0E598800C5C1D0 /* RPC.swift */,
+			);
+			path = rpc;
+			sourceTree = "<group>";
+		};
+		93B626621C0E598800C5C1D0 /* rt */ = {
+			isa = PBXGroup;
+			children = (
+				93B626631C0E598800C5C1D0 /* Runtime.swift */,
+				93B626641C0E598800C5C1D0 /* Security.swift */,
+			);
+			path = rt;
+			sourceTree = "<group>";
+		};
+		93B626651C0E598800C5C1D0 /* util */ = {
+			isa = PBXGroup;
+			children = (
+				93B626661C0E598800C5C1D0 /* Dates.swift */,
+				93B626671C0E598800C5C1D0 /* Locking.swift */,
+				93B626681C0E598800C5C1D0 /* Logging.swift */,
+				93B626691C0E598800C5C1D0 /* Promise.swift */,
+				93B6266A1C0E598800C5C1D0 /* Strings.swift */,
+				93B6266B1C0E598800C5C1D0 /* Threads.swift */,
+			);
+			path = util;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		939417031BF547AB00F3F996 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9306FB831BFC012500DE7190 /* rt.h in Headers */,
+				9306FB841BFC012500DE7190 /* ios.h in Headers */,
+				9306529E1BFD0E3F0093B650 /* types.h in Headers */,
+				930652A51BFD42BC0093B650 /* rpc.h in Headers */,
+				930652A11BFD236E0093B650 /* context.h in Headers */,
+				9394170A1BF547AB00F3F996 /* v23.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		939417051BF547AB00F3F996 /* v23 */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 9394171A1BF547AB00F3F996 /* Build configuration list for PBXNativeTarget "v23" */;
+			buildPhases = (
+				939417011BF547AB00F3F996 /* Sources */,
+				939417021BF547AB00F3F996 /* Frameworks */,
+				939417031BF547AB00F3F996 /* Headers */,
+				939417041BF547AB00F3F996 /* Resources */,
+				9306FB481BFAA66300DE7190 /* Copy Files */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = v23;
+			productName = v23;
+			productReference = 939417061BF547AB00F3F996 /* v23.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+		9394170F1BF547AB00F3F996 /* v23Tests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 9394171D1BF547AB00F3F996 /* Build configuration list for PBXNativeTarget "v23Tests" */;
+			buildPhases = (
+				9394170C1BF547AB00F3F996 /* Sources */,
+				9394170D1BF547AB00F3F996 /* Frameworks */,
+				9394170E1BF547AB00F3F996 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				939417131BF547AB00F3F996 /* PBXTargetDependency */,
+			);
+			name = v23Tests;
+			productName = v23Tests;
+			productReference = 939417101BF547AB00F3F996 /* v23Tests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		939416FD1BF547AB00F3F996 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0710;
+				LastUpgradeCheck = 0710;
+				ORGANIZATIONNAME = "Google Inc.";
+				TargetAttributes = {
+					939417051BF547AB00F3F996 = {
+						CreatedOnToolsVersion = 7.1;
+					};
+					9394170F1BF547AB00F3F996 = {
+						CreatedOnToolsVersion = 7.1;
+					};
+				};
+			};
+			buildConfigurationList = 939417001BF547AB00F3F996 /* Build configuration list for PBXProject "v23" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 939416FC1BF547AB00F3F996;
+			productRefGroup = 939417071BF547AB00F3F996 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				939417051BF547AB00F3F996 /* v23 */,
+				9394170F1BF547AB00F3F996 /* v23Tests */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		939417041BF547AB00F3F996 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9394170E1BF547AB00F3F996 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		939417011BF547AB00F3F996 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				93B6266E1C0E598800C5C1D0 /* Types.swift in Sources */,
+				93B626751C0E598800C5C1D0 /* Logging.swift in Sources */,
+				93B6266F1C0E598800C5C1D0 /* Context.swift in Sources */,
+				93B626781C0E598800C5C1D0 /* Threads.swift in Sources */,
+				93B6266C1C0E598800C5C1D0 /* Errors.swift in Sources */,
+				93B6266D1C0E598800C5C1D0 /* Refs.swift in Sources */,
+				93B626711C0E598800C5C1D0 /* Runtime.swift in Sources */,
+				93B626741C0E598800C5C1D0 /* Locking.swift in Sources */,
+				93B626701C0E598800C5C1D0 /* RPC.swift in Sources */,
+				93B626761C0E598800C5C1D0 /* Promise.swift in Sources */,
+				93B626721C0E598800C5C1D0 /* Security.swift in Sources */,
+				93B626771C0E598800C5C1D0 /* Strings.swift in Sources */,
+				93B626731C0E598800C5C1D0 /* Dates.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		9394170C1BF547AB00F3F996 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				939417161BF547AB00F3F996 /* v23Tests.swift in Sources */,
+				93B626511C0D5D3F00C5C1D0 /* PromiseTests.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		939417131BF547AB00F3F996 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 939417051BF547AB00F3F996 /* v23 */;
+			targetProxy = 939417121BF547AB00F3F996 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		939417181BF547AB00F3F996 /* 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;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = 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_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;
+				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;
+		};
+		939417191BF547AB00F3F996 /* 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.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				VALIDATE_PRODUCT = YES;
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = "";
+			};
+			name = Release;
+		};
+		9394171B1BF547AB00F3F996 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_MODULES = YES;
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				INFOPLIST_FILE = v23/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/v23",
+					"$(PROJECT_DIR)/v23/x",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.v23;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+			};
+			name = Debug;
+		};
+		9394171C1BF547AB00F3F996 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_MODULES = YES;
+				DEFINES_MODULE = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				DYLIB_INSTALL_NAME_BASE = "@rpath";
+				INFOPLIST_FILE = v23/Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/v23",
+					"$(PROJECT_DIR)/v23/x",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.v23;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		9394171E1BF547AB00F3F996 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				INFOPLIST_FILE = v23Tests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.v23Tests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		9394171F1BF547AB00F3F996 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				INFOPLIST_FILE = v23Tests/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = v.io.v23Tests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		939417001BF547AB00F3F996 /* Build configuration list for PBXProject "v23" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				939417181BF547AB00F3F996 /* Debug */,
+				939417191BF547AB00F3F996 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		9394171A1BF547AB00F3F996 /* Build configuration list for PBXNativeTarget "v23" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9394171B1BF547AB00F3F996 /* Debug */,
+				9394171C1BF547AB00F3F996 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		9394171D1BF547AB00F3F996 /* Build configuration list for PBXNativeTarget "v23Tests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9394171E1BF547AB00F3F996 /* Debug */,
+				9394171F1BF547AB00F3F996 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 939416FD1BF547AB00F3F996 /* Project object */;
+}
diff --git a/lib/v23.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/lib/v23.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..32ad0fa
--- /dev/null
+++ b/lib/v23.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:v23.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/lib/v23/Info.plist b/lib/v23/Info.plist
new file mode 100644
index 0000000..d3de8ee
--- /dev/null
+++ b/lib/v23/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>NSPrincipalClass</key>
+	<string></string>
+</dict>
+</plist>
diff --git a/lib/v23/bridge/Errors.swift b/lib/v23/bridge/Errors.swift
new file mode 100644
index 0000000..4e8bf74
--- /dev/null
+++ b/lib/v23/bridge/Errors.swift
@@ -0,0 +1,70 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+public struct VError : ErrorType {
+  public let identity:String
+  public let action:ErrorAction
+  public let msg:String?
+  public let stacktrace:String?
+  public static var _delegate:_VErrorHandler = DefaultVErrorHandler()
+}
+
+public protocol _VErrorHandler {
+  func lookupErr(err:VError) -> ErrorType
+  func doThrow(err:VError) throws
+}
+
+public struct DefaultVErrorHandler:  _VErrorHandler {
+  public func lookupErr(err:VError) -> ErrorType {
+    return err
+  }
+  
+  public func doThrow(err:VError) throws {
+    log.warning("Throwing low-level error without handler (did VDL generation fail?):\n\tIdentity: " +
+      "\(err.identity)\n\tAction: \(err.action)\n\tMsg: \(err.msg ?? "")\n\tStacktrace: \(err.stacktrace ?? "")")
+    throw err
+  }
+}
+
+/// SwiftVError is the C struct that the go bridge uses to transfer an error to Swift.
+internal extension SwiftVError {
+  internal func isEmpty() -> Bool { return identity == nil || identity.memory == 0 }
+ 
+  /// Helper to run a go-bridge method that might fill out this struct on error. In that scenario
+  /// we translate that into a Swift-based error and throw it.
+  /// VError's static _delegate slot is the actual function that throws a given converted VError
+  /// into its apropriate enum-based error. That error will be generated from the VDL, which is why
+  /// we need this hook here. A default handler just throws the VError itself, which is of ErrorType.
+  internal static func catchAndThrowError<T>(@noescape block: UnsafeMutablePointer<SwiftVError>->T) throws -> T {
+    let ptr = UnsafeMutablePointer<SwiftVError>.alloc(1)
+    defer { ptr.dealloc(1) }
+    ptr.initialize(SwiftVError())
+    let ret = block(ptr)
+    let verr = ptr.memory
+    if !verr.isEmpty() {
+      let err = verr.toSwift()
+      try VError._delegate.doThrow(err)
+    }
+    return ret
+  }
+
+  /// Convert the C Struct into a Swift-based VError struct. 
+  /// Go allocates the underlying strings, and swift must take control of them and free them when done
+  internal func toSwift() -> VError {
+    return VError(
+      identity: String.fromCStringNoCopy(identity, freeWhenDone: true)!,
+      action: ErrorAction.init(rawValue: UInt32(actionCode)) ?? ErrorAction.NoRetry,
+      msg: String.fromCStringNoCopy(msg, freeWhenDone: true),
+      stacktrace: String.fromCStringNoCopy(stacktrace, freeWhenDone: true))
+  }
+}
+
+public enum ErrorAction: UInt32 {
+  case NoRetry = 0 // Do not retry.
+  case RetryConnection = 1 // Renew high-level connection/context.
+  case RetryRefetch = 2 // Refetch and retry (e.g., out of date HTTP ETag)
+  case RetryBackoff = 3 // Backoff and retry a finite number of times.
+}
diff --git a/lib/v23/bridge/Refs.swift b/lib/v23/bridge/Refs.swift
new file mode 100644
index 0000000..84acc79
--- /dev/null
+++ b/lib/v23/bridge/Refs.swift
@@ -0,0 +1,37 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/// Class to hold onto promises that get referenced by AsyncId between Go and Swift.
+/// The larger motivation is closures that get passed as function pointers have to be 'context-free'
+/// so we can't closure on a reference to a given future. By allowing the end user to hold onto
+/// this in various places (strongly typed to the appropriate ResloveType) then we can pass a handle
+/// back and forth safely.
+internal class GoPromises<ResolveType> : Lockable {
+  typealias AsyncId = Int32
+  private (set) var lastId:AsyncId = 0
+  private var promises = [AsyncId:Promise<ResolveType>]()
+  private let timeoutDelay:NSTimeInterval?
+  internal init(timeout:NSTimeInterval?) {
+    timeoutDelay = timeout
+  }
+  
+  internal func newPromise() -> (AsyncId, Promise<ResolveType>) {
+    let p = Promise<ResolveType>()
+    if let timeout = timeoutDelay { p.rejectAfterDelay(delay: timeout) }
+    let asyncId = OSAtomicIncrement32(&lastId)
+    lock { self.promises[asyncId] = p }
+    p.always { _ in
+      // Guaruntee we delete the ref on resolution 
+      // (can happen on delayed timeout that it wouldn't get cleaned)
+      self.lock { self.promises[asyncId] = nil }
+    }
+    return (asyncId, p)
+  }
+  
+  internal func getAndDeleteRef(asyncId:AsyncId) -> Promise<ResolveType>? {
+    guard let p = promises[asyncId] else { return nil }
+    lock { self.promises[asyncId] = nil }
+    return p
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/bridge/Types.swift b/lib/v23/bridge/Types.swift
new file mode 100644
index 0000000..e912856
--- /dev/null
+++ b/lib/v23/bridge/Types.swift
@@ -0,0 +1,114 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+extension Bool {
+  public func toGo() -> GoUint8 { if (self) { return GoUint8(1) } else { return GoUint8(0) } }
+}
+
+extension Int {
+  public func toGo() -> GoInt { return GoInt(self) }
+}
+
+extension Int32 {
+  public func toGo() -> GoInt32 { return GoInt32(self) }
+}
+
+extension Int8 {
+  public func toGo() -> GoInt8 { return GoInt8(self) }
+}
+
+extension Float {
+  public func toGo() -> GoFloat32 { return GoFloat32(self) }
+}
+
+extension Double {
+  public func toGo() -> GoFloat64 { return GoFloat64(self) }
+}
+
+extension String {
+  public func toGo() -> UnsafeMutablePointer<Int8> { return UnsafeMutablePointer<Int8>((self as NSString).UTF8String) }
+}
+
+/// Currently this is unused as it's not guarunteed past 1.x cgo
+//extension GoString {
+//  /// Given a string optional, call a block with an UTF8 copy version of a Go String, which itself is
+//  /// annotated such that that the closed string shouldn't escape this block. That way we can be
+//  /// safe about making sure the underlying c-string reference stays in memory for the duration
+//  /// of the pointer usage, and Swift is the one ultimately responsible for its garbage collection.
+//  public static func inScope(strOpt:String?, @noescape block: GoString->Void) {
+//    guard let str = strOpt else {
+//      block(empty)
+//      return
+//    }
+//    
+//    // We use the NSString bridge as its an order of magnitude faster than using nulTerminatedUtf8,
+//    // the UTF8 views, or withCString as of Swift 2.1 (11/17/15)
+//    let utf8 = (str as NSString).UTF8String
+//    let goStr = GoString(p: UnsafeMutablePointer<Int8>(utf8), n: GoInt(strlen(utf8)))
+//    block(goStr)
+//  }
+//  
+//  /// An empty (nil) string
+//  static let empty = GoString(p: nil, n: 0)
+//}
+
+extension SwiftByteArrayArray : CollectionType, CustomDebugStringConvertible {
+  public typealias Index = Int
+  
+  public var startIndex: Int {
+    return 0
+  }
+  
+  public var endIndex: Int {
+    return count()
+  }
+  
+  public subscript(i: Int) -> SwiftByteArray {
+    return data[i]
+  }
+  
+  public func count() -> Int { return Int(length) }
+  
+  public func dealloc() {
+    for i in 0..<length {
+      let byteArray = data[Int(i)]
+      byteArray.dealloc()
+    }
+    data.dealloc(count())
+  }
+  
+  public var debugDescription: String {
+    get {
+      var totalSize = 0
+      for byteArray in self {
+        totalSize += Int(byteArray.length)
+      }
+      return "[SwiftByteArrayArray length=\(length) totalHoldingSize=\(totalSize) data=\(data)]"
+    }
+  }
+}
+
+extension SwiftByteArray : CustomDebugStringConvertible {
+  public func count() -> Int { return Int(length) }
+  
+  public func dealloc() {
+    data.dealloc(count())
+  }
+  
+  public func toNSDataNoCopyNoFree() -> NSData {
+    return NSData(bytesNoCopy: data, length: count(), freeWhenDone: false)
+  }
+  
+  public var debugDescription: String {
+    get {
+      let utf8 = NSString(
+        bytes: data,
+        length: Int(length),
+        encoding: NSUTF8StringEncoding)
+      return "[SwiftByteArray length=\(length) dataInUtf8=\(utf8)]"
+    }
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/context/Context.swift b/lib/v23/context/Context.swift
new file mode 100644
index 0000000..217b61a
--- /dev/null
+++ b/lib/v23/context/Context.swift
@@ -0,0 +1,171 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+public struct Context {
+  internal var handle:ContextHandle {
+    didSet {
+      log.debug("Updated context \(self)")
+    }
+  }
+  private var _isCancelled:Bool = false
+  private var _isCancellable:Bool = false
+  private var dirty:ContextFeatures = []
+  public var userInfo:[String: Any] = [:]
+  
+  internal init(handle:ContextHandle) {
+    self.handle = handle
+  }
+  
+  internal init(handle:ContextHandle, existingDeadline:NSDate?, isCancellable:Bool) {
+    self.handle = handle
+    self.deadline = existingDeadline
+    self._isCancellable = isCancellable
+  }
+  
+  public mutating func client() throws -> Client {
+    try updateHandleIfNeeded()
+    return Client(defaultContext: self)
+  }
+  
+  public var deadline:NSDate? {
+    didSet {
+      guard oldValue != deadline else { return }
+      guard deadline != nil else {
+        log.warning("Cannot undo a deadline once one has been set. Instead mutate the root context. This will no-op.")
+        deadline = oldValue // TODO Verify that the following didSet won't be a problem
+        return
+      }
+      //      guard oldValue == nil || deadline!.isBefore(oldValue!) else {
+      //        log.warning("Cannot set a deadline that is after the old value. Instead mutate the root context. This will no-op.")
+      //        deadline = oldValue // TODO Verify that the following didSet won't be a problem
+      //        return
+      //      }
+      dirty.insert(ContextFeatures.Deadline)
+    }
+  }
+  
+  public var isCancelled:Bool { return _isCancelled }
+  
+  public var isCancellable:Bool {
+    get {
+      return !_isCancelled && (_isCancellable || dirty.contains(ContextFeatures.Cancellable))
+    }
+    set {
+      guard _isCancellable != newValue else { return }
+      guard newValue == true else {
+        log.warning("Cannot set something as not cancellable once it already is marked as such. No-op.")
+        return
+      }
+      // This shouldn't be possible given we were marked as not cancellable previously.
+      guard !_isCancelled else {
+        log.warning("Already cancelled, so this is a no-op.")
+        return
+      }
+      dirty.insert(ContextFeatures.Cancellable)
+    }
+  }
+  
+  /// Cancels all associated RPC with this context and renders it unusable. Call newContext afterwards
+  /// to get a similar context that is workable.
+  ///
+  /// If this context is not cancellable (it has already been cancelled, or a deadline/timeout
+  /// was never set), then this will throw a ContextError.
+  ///
+  /// If it does not throw right away, the promise will never fail.
+  private static let outstandingCancels = GoPromises<Void>(timeout: nil)
+  public mutating func cancel() throws -> Promise<Void> {
+    guard !_isCancelled else { throw ContextError.ContextIsAlreadyCancelled }
+    guard _isCancellable else { throw ContextError.ContextNotCancellable }
+    _isCancelled = true
+    let (asyncId, p) = Context.outstandingCancels.newPromise()
+    ios_io_v_v23_context_CancelableVContext_nativeCancelAsync(handle.goHandle, asyncId, { asyncId in
+      if let p = Context.outstandingCancels.getAndDeleteRef(asyncId) {
+        RunOnMain {
+          do {
+            try p.resolve()
+          } catch let e {
+            log.warning("Unable to resolve cancel async promise: \(e)")
+          }
+        }
+      }
+    })
+    return p
+  }
+  
+  internal mutating func updateHandleIfNeeded() throws {
+    if (_isCancelled) {
+      throw ContextError.ContextIsAlreadyCancelled
+    }
+    
+    if dirty.contains(ContextFeatures.Deadline) {
+      try updateHandleForDeadline()
+    }
+    
+    if dirty.contains(ContextFeatures.Cancellable) {
+      try updateHandleForCancellable()
+    }
+  }
+  
+  private mutating func updateHandleForDeadline() throws {
+    guard let deadline = deadline else {
+      fatalError("Deadline was assumed to not be nil here, yet was marked as dirty")
+    }
+    let goHandle = try SwiftVError.catchAndThrowError { errPtr in
+      return ios_io_v_v23_context_VContext_nativeWithDeadline(
+        self.handle.goHandle, deadline.timeIntervalSince1970, errPtr)
+    }
+    _isCancellable = true
+    dirty.remove(ContextFeatures.Deadline)
+    handle = ContextHandle(goHandle)
+  }
+  
+  private mutating func updateHandleForCancellable() throws {
+    let goHandle = try SwiftVError.catchAndThrowError { errPtr in
+      return ios_io_v_v23_context_VContext_nativeWithCancel(
+        self.handle.goHandle, errPtr)
+    }
+    _isCancellable = true
+    dirty.remove(ContextFeatures.Cancellable)
+    handle = ContextHandle(goHandle)
+  }
+  
+  internal mutating func run<T>(@autoclosure block: () throws ->T) throws -> T {
+    guard !_isCancelled else { throw ContextError.ContextIsAlreadyCancelled }
+    try updateHandleIfNeeded()
+    return try block()
+  }
+}
+
+public class ContextHandle: CustomStringConvertible, CustomDebugStringConvertible {
+  internal let goHandle:GoContextHandle
+  
+  internal init(_ goHandle:GoContextHandle) {
+    self.goHandle = goHandle
+  }
+
+  deinit {
+    if goHandle != 0 {
+      ios_io_v_v23_context_VContext_nativeFinalize(goHandle)
+    }
+  }
+  
+  public var description: String { return "[ContextHandle \(goHandle)]" }
+  public var debugDescription: String { return "[ContextHandle handle=\(goHandle)]" }
+}
+
+struct ContextFeatures: OptionSetType {
+  let rawValue: Int
+  static let Deadline = ContextFeatures(rawValue: 1 << 1)
+  static let Cancellable = ContextFeatures(rawValue: 1 << 2)
+  // Make sure to add any new ones to updateHandleIfNeeded
+  // Unforutnately Swift doesn't yet give us a good enum-style way to iterate on this and prevent
+  // future bugs.
+}
+
+enum ContextError: ErrorType {
+  case ContextNotCancellable
+  case ContextIsAlreadyCancelled
+}
diff --git a/lib/v23/rpc/RPC.swift b/lib/v23/rpc/RPC.swift
new file mode 100644
index 0000000..03d31ad
--- /dev/null
+++ b/lib/v23/rpc/RPC.swift
@@ -0,0 +1,183 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+public typealias BlessingPattern = String
+public typealias GranterHandle = Int32
+
+public enum RpcClientOption {
+  case AllowedServersPolicy(polices:[BlessingPattern])
+  case RetryTimeout(timeout:NSTimeInterval)
+  case Granter(granter:GranterHandle)
+}
+
+public struct Client {
+  internal let defaultContext:Context
+  
+  internal init(defaultContext:Context) {
+    self.defaultContext = defaultContext
+  }
+  
+  internal func ctxHandle(ctx:Context?) -> ContextHandle {
+    return (ctx ?? defaultContext).handle
+  }
+  
+  public func startCall(ctx:Context?=nil, name:String, method:String, args:[AnyObject]?=nil, returnArgsLength:Int,
+                        skipServerAuth:Bool=false) -> Promise<ClientCall> {
+    let vomArgs = SwiftByteArrayArray(length: 0, data: nil)
+
+    let (asyncId, handleP) = Client.outstandingHandles.newPromise()
+    ios_io_v_impl_google_rpc_ClientImpl_nativeStartCallAsync(
+      self.ctxHandle(ctx).goHandle,
+      name.toGo(),
+      method.toGo(),
+      vomArgs,
+      skipServerAuth.toGo(),
+      asyncId,
+      { asyncId, handle in Client.callDidSucceed(asyncId, handle: handle) },
+      { asyncId, err in Client.callDidFail(asyncId, err: err) })
+    return handleP.then { handle throws in
+      return try ClientCall(
+        ctxHandle: self.ctxHandle(ctx), callHandle: handle, returnArgsLength: returnArgsLength)
+    }
+  }
+ 
+  private static let outstandingHandles = GoPromises<GoClientCallHandle>(timeout: nil)
+  
+  public func call(ctx:Context?=nil, name:String, method:String, args:[AnyObject]?=nil, returnArgsLength:Int,
+                   skipServerAuth:Bool=false) -> Promise<[AnyObject]?> {
+    return startCall(
+        ctx,
+        name: name,
+        method: method,
+        args: args,
+        returnArgsLength: returnArgsLength,
+        skipServerAuth: skipServerAuth)
+      .then { call throws -> Promise<[AnyObject]?> in
+      return try call.finish()
+    }
+  }
+
+  internal static func callDidSucceed(asyncId:AsyncCallbackIdentifier, handle:_GoHandle) {
+    if let p = Client.outstandingHandles.getAndDeleteRef(asyncId) {
+      RunOnMain {
+        do {
+          try p.resolve(handle)
+        } catch let e {
+          log.warning("Unable to resolve asyncCall start with handle \(handle): \(e)")
+        }
+      }
+    }
+  }
+  
+  internal static func callDidFail(asyncId:AsyncCallbackIdentifier, err:SwiftVError) {
+    let verr = VError._delegate.lookupErr(err.toSwift())
+    if let p = Client.outstandingHandles.getAndDeleteRef(asyncId) {
+      RunOnMain {
+        do {
+          try p.reject(verr)
+        } catch let e {
+          log.warning("Unable to reject asyncCall start with err \(verr): \(e)")
+        }
+      }
+    }
+  }
+  
+  public func close(ctx:Context?=nil) {
+    ios_io_v_impl_google_rpc_ClientImpl_nativeClose(ctxHandle(ctx).goHandle)
+  }
+}
+
+public enum ClientCallErrors: ErrorType {
+  case NilHandlerOnInit
+}
+
+public class ClientCall {
+  internal let ctxHandle:ContextHandle
+  internal let callHandle:GoClientCallHandle
+  internal let returnArgsLength:Int
+ 
+  internal init(ctxHandle:ContextHandle, callHandle:GoClientCallHandle, returnArgsLength:Int) throws {
+    self.ctxHandle = ctxHandle
+    self.callHandle = callHandle
+    self.returnArgsLength = returnArgsLength
+    guard callHandle != 0 else {
+      throw ClientCallErrors.NilHandlerOnInit
+    }
+  }
+  
+  deinit {
+    if callHandle != 0 {
+      ios_io_v_impl_google_rpc_ClientCallImpl_nativeFinalize(callHandle)
+    }
+  }
+  
+  public func closeSend() throws {
+    try SwiftVError.catchAndThrowError { errPtr in
+      ios_io_v_impl_google_rpc_ClientCallImpl_nativeCloseSend(ctxHandle.goHandle, callHandle, errPtr)
+    }
+  }
+ 
+  private static let outstandingFinishes = GoPromises<[AnyObject]?>(timeout: nil)
+  public func finish() throws -> Promise<[AnyObject]?> {
+    let (asyncId, p) = ClientCall.outstandingFinishes.newPromise()
+    ios_io_v_impl_google_rpc_ClientCallImpl_nativeFinishAsync(
+      ctxHandle.goHandle, callHandle, returnArgsLength.toGo(), asyncId,
+      { asyncId, byteArrayArray in ClientCall.finishDidSucceed(asyncId, byteArrayArray: byteArrayArray) },
+      { asyncId, err in ClientCall.finishDidFail(asyncId, err: err) })
+    return p
+  }
+
+  internal static func finishDidSucceed(asyncId:AsyncCallbackIdentifier, byteArrayArray:SwiftByteArrayArray) {
+    guard let p = ClientCall.outstandingFinishes.getAndDeleteRef(asyncId) else {
+      log.warning("Couldn't find associated promise for finish succeeding on asyncId \(asyncId)")
+      // Deallocate associated bytes malloc'd in Go
+      byteArrayArray.dealloc()
+      return
+    }
+   
+    // VOM decode in background to let Go get free'd up and to not block main
+    RunInBackground {
+      // Deallocate associated bytes malloc'd in Go
+      defer { byteArrayArray.dealloc() }
+      
+      do {
+        // TODO Decode via VOM
+//        log.debug("Got back byteArrayArray \(byteArrayArray) and data \(byteArrayArray.data)")
+//        var i = 0
+//        for byteArray in byteArrayArray {
+//          log.debug("Byte array \(i): \(byteArray)")
+//          i += 1
+//        }
+      } catch let e {
+        do { try p.reject(e) } catch {}
+        return
+      }
+      
+      do {
+        try p.resolve(nil)
+      } catch let e {
+        log.warning("Unable to resolve finish promise: \(e)")
+      }
+    }
+  }
+  
+  internal static func finishDidFail(asyncId:AsyncCallbackIdentifier, err:SwiftVError) {
+    let verr = VError._delegate.lookupErr(err.toSwift())
+    if let p = ClientCall.outstandingFinishes.getAndDeleteRef(asyncId) {
+      RunOnMain {
+        do {
+          try p.reject(verr)
+        } catch let e {
+          log.warning("Unable to reject finish with err \(verr): \(e)")
+        }
+      }
+    }
+  }
+  
+  public func remoteBlessings() -> (blessings:[String], cryptoBlessings:[Blessings]) {
+    fatalError("Unimplemented")
+  }
+}
diff --git a/lib/v23/rt/Runtime.swift b/lib/v23/rt/Runtime.swift
new file mode 100644
index 0000000..6397692
--- /dev/null
+++ b/lib/v23/rt/Runtime.swift
@@ -0,0 +1,67 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+public func configure(loggingOptions:VLoggingOptions?=nil) throws {
+  try V23.configure(loggingOptions)
+}
+
+public let instance = V23.instance
+
+public class V23 {
+  private static var _instance: V23? = nil
+  private var rootContext:Context
+
+  /// The singleton instance of V23 that you use to create and configure any clients/servers.
+  ///
+  /// **Warning:** You must first call configure before you can grab an instance. It will
+  /// crash with a fatalError otherwise.
+  public static var instance: V23 {
+    get {
+      if (_instance == nil) {
+        fatalError("You must first call V23.configure before you can use an instance")
+      }
+      return _instance!
+    }
+    set {
+      if (_instance != nil) {
+        fatalError("You cannot create another instance of V23")
+      }
+      _instance = newValue
+    }
+  }
+  
+  /// Private constructor for V23.
+  private init(loggingOptions:VLoggingOptions) throws {
+    // We must have all variables initialized before we can throw
+    rootContext = Context(handle: ContextHandle(0))
+    try SwiftVError.catchAndThrowError { errPtr in
+      ios_io_v_v23_V_nativeInitGlobal(errPtr)
+    }
+    try loggingOptions.initGo()
+    rootContext = Context(handle: ContextHandle(ios_io_v_impl_google_rt_VRuntimeImpl_nativeInit()))
+  }
+  
+  deinit {
+    ios_io_v_impl_google_rt_VRuntimeImpl_nativeShutdown(rootContext.handle.goHandle)
+  }
+  
+  /// You must call configure before using Vanadium or grabbing an instance.
+  /// This is where you pass any logging options... (TBD)
+  ///
+  /// **Warning:** You may only call this once. It will otherwise crash with a fatalError.
+  ///
+  /// :param: loggingOptions Logging options used by the Vandadium internals. 
+  ///         See documentation on VLoggingOptions for more information
+  public class func configure(loggingOptions:VLoggingOptions?=nil) throws {
+    instance = try V23(loggingOptions: loggingOptions ?? VLoggingOptions())
+  }
+  
+  public var context: Context {
+    get {
+      return rootContext
+    }
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/rt/Security.swift b/lib/v23/rt/Security.swift
new file mode 100644
index 0000000..320091b
--- /dev/null
+++ b/lib/v23/rt/Security.swift
@@ -0,0 +1,38 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+import Security
+
+public typealias Hash = String
+public struct PublicKey {
+  let hash:Hash
+  let derPkix:[UInt8]
+}
+
+public struct Caveat {
+  let id:[UInt8] // likely a UUID
+  let paramVom:[UInt8] // // VOM-encoded bytes of the parameters to be provided to the validation function.
+}
+
+public struct Signature {
+  let purpose:[UInt8]
+  let hash:Hash
+  let r:[UInt8]
+  let s:[UInt8]
+}
+
+public struct Certificate {
+  let extensionStr:String // Human-readable string extension bound to PublicKey
+  let publicKey:[UInt8] // DER-encoded PKIX public key
+  let caveats:[Caveat]
+  let signature:Signature
+}
+
+public struct Blessings {
+  let chains:[[Certificate]]
+  let publicKey:PublicKey
+  let digests:[[UInt8]]
+  let uniqueId:[UInt8]
+}
diff --git a/lib/v23/util/Dates.swift b/lib/v23/util/Dates.swift
new file mode 100644
index 0000000..6b4f087
--- /dev/null
+++ b/lib/v23/util/Dates.swift
@@ -0,0 +1,15 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+internal extension NSDate {
+  internal func isBefore(otherDate:NSDate) -> Bool {
+    return otherDate.timeIntervalSinceReferenceDate < self.timeIntervalSinceReferenceDate
+  }
+
+  internal func isAfter(otherDate:NSDate) -> Bool {
+    return otherDate.timeIntervalSinceReferenceDate < self.timeIntervalSinceReferenceDate
+  }
+}
diff --git a/lib/v23/util/Locking.swift b/lib/v23/util/Locking.swift
new file mode 100644
index 0000000..0f6bee2
--- /dev/null
+++ b/lib/v23/util/Locking.swift
@@ -0,0 +1,17 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+protocol Lockable {
+  func lock(block:()->())
+}
+
+extension Lockable where Self : AnyObject {
+  func lock(block:()->()) {
+    objc_sync_enter(self)
+    block()
+    objc_sync_exit(self)
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/util/Logging.swift b/lib/v23/util/Logging.swift
new file mode 100644
index 0000000..1ec6e48
--- /dev/null
+++ b/lib/v23/util/Logging.swift
@@ -0,0 +1,103 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+internal let log = VLogger()
+
+public struct VLogger {
+  internal func debug(@autoclosure closure: () -> String, functionName: String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) {
+    log("DEBUG", str: closure(), functionName: functionName, fileName: fileName, lineNumber: lineNumber)
+  }
+  
+  internal func info(@autoclosure closure: () -> String, functionName: String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) {
+    log("INFO", str: closure(), functionName: functionName, fileName: fileName, lineNumber: lineNumber)
+  }
+  
+  internal func warning(@autoclosure closure: () -> String, functionName: String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) {
+    log("WARN", str: closure(), functionName: functionName, fileName: fileName, lineNumber: lineNumber)
+  }
+  
+  internal func error(@autoclosure closure: () -> String, functionName: String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) {
+    log("ERROR", str: closure(), functionName: functionName, fileName: fileName, lineNumber: lineNumber)
+  }
+  
+  internal func fatal(@autoclosure closure: () -> String, functionName: String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) {
+    log("FATAL", str: closure(), functionName: functionName, fileName: fileName, lineNumber: lineNumber)
+  }
+  
+  private func log(level:String, str:String, functionName: String = __FUNCTION__, fileName: String = __FILE__, lineNumber: Int = __LINE__) {
+    if let threadName = NSThread.currentThread().name where threadName != "" {
+      print("[", level, "] ", (fileName as NSString).lastPathComponent, ":", lineNumber, " (", threadName, ") ", str, separator: "")
+    } else {
+      print("[", level, "] ", (fileName as NSString).lastPathComponent, ":", lineNumber, " ", str, separator: "")
+    }
+  }
+}
+
+public enum VLogLevel: Int {
+  case Info = 0
+  case Warning = 1
+  case Error = 2
+  case Fatal = 3
+}
+
+public struct VLoggingOptions {
+  /// Enable V-leveled logging at the specified level.
+  let level: VLogLevel
+  
+  /// The syntax of the argument is a comma-separated list of pattern=N,
+  /// where pattern is a literal file name (minus the ".go" suffix) or
+  /// "glob" pattern and N is a V level. For instance, gopher*=3
+  /// sets the V level to 3 in all Go files whose names begin "gopher".
+  let moduleSpec: String?
+  
+  // We only log to disk on OS X
+  #if os(OSX)
+  /// If true, logs are written to standard error instead of to files
+  let logToStderrOnly: Bool
+  
+  /// Log files will be wirtten to this directory instead of the default temp dir
+  let logDir: String?
+  #endif
+  
+  #if os(OSX)
+  public init(level:VLogLevel=VLogLevel.Info,
+      moduleSpec:String?=nil,
+      logToStderrOnly:Bool=true,
+      logDir:String?=nil) {
+    self.level = level
+    self.moduleSpec = moduleSpec
+    self.logToStderrOnly = logToStderrOnly
+    self.logDir = logDir
+    if (self.logToStderrOnly && self.logDir != nil) {
+      NSLog("WARNING: logToStderrOnly set to true and logDir was set -- only logging to stderr and not to disk.")
+    }
+  }
+  #else
+  public init(level:VLogLevel=VLogLevel.Info, moduleSpec:String?=nil) {
+    self.level = level
+    self.moduleSpec = moduleSpec
+  }
+  #endif
+ 
+  /// Call the init logging function in go -- INTERNAL ONLY
+  internal func initGo() throws {
+    #if os(OSX)
+      try SwiftVError.catchAndThrowError({ errPtr in
+        ios_io_v_v23_V_nativeInitLogging(
+          logDir?.toGo() ?? nil,
+          logToStderrOnly.toGo(),
+          level.rawValue.toGo(),
+          moduleSpec?.toGo() ?? nil,
+          errPtr)
+      })
+    #else
+      try SwiftVError.catchAndThrowError({ errPtr in
+        ios_io_v_v23_V_nativeInitLogging(nil, 0, // no logging to disk
+            level.rawValue.toGo(), moduleSpec?.toGo() ?? nil, errPtr)
+      })
+    #endif
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/util/Promise.swift b/lib/v23/util/Promise.swift
new file mode 100644
index 0000000..2d93fdb
--- /dev/null
+++ b/lib/v23/util/Promise.swift
@@ -0,0 +1,329 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+public enum PromiseErrors<ResolveType>: ErrorType {
+  case AlreadyResolved(existingObj:ResolveType)
+  case AlreadyRejected(existingErr:ErrorType?)
+  case Timeout
+}
+
+public class Promise<ResolveType> : Lockable {
+  private var resolveCallbacks:[(dispatch_queue_t?, ResolveType->())]? = nil
+  private var rejectCallbacks:[(dispatch_queue_t?, ErrorType?->())]? = nil
+  private var alwaysCallbacks:[(dispatch_queue_t?, Resolution<ResolveType>->())]? = nil
+  private let resolutionSemaphore = dispatch_semaphore_create(0)
+  
+  internal var status: Resolution<ResolveType> = Resolution.Pending {
+    didSet {
+      updatedStatus()
+    }
+  }
+  
+  public init() { }
+  
+  public convenience init(resolved obj: ResolveType) {
+    self.init()
+    status = Resolution.Resolved(obj: obj)
+  }
+
+  public convenience init(rejected err: ErrorType?) {
+    self.init()
+    status = Resolution.Rejected(err: err)
+  }
+  
+  // Resolve/reject
+  public func resolve(obj:ResolveType) throws {
+    objc_sync_enter(self)
+    defer { objc_sync_exit(self) }
+    switch (status) {
+    case .Rejected(let err): throw PromiseErrors<ResolveType>.AlreadyRejected(existingErr: err)
+    case .Resolved(let obj): throw PromiseErrors<ResolveType>.AlreadyResolved(existingObj: obj)
+    case .Pending: status = Resolution.Resolved(obj: obj)
+    }
+  }
+  
+  public func reject(err:ErrorType?) throws {
+    objc_sync_enter(self)
+    defer { objc_sync_exit(self) }
+    switch (status) {
+    case .Rejected(let err): throw PromiseErrors<ResolveType>.AlreadyRejected(existingErr: err)
+    case .Resolved(let obj): throw PromiseErrors<ResolveType>.AlreadyResolved(existingObj: obj)
+    case .Pending: status = Resolution.Rejected(err: err)
+    }
+  }
+
+  // Chain/handle state
+  public func onResolve(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+                        _ callback:ResolveType->()) -> Promise<ResolveType> {
+    objc_sync_enter(self)
+    defer { objc_sync_exit(self) }
+    switch(status) {
+    case .Resolved(let obj): dispatch_maybe_async(queue, block: { callback(obj) })
+    case .Rejected: break
+    case .Pending:
+      if resolveCallbacks == nil {
+        resolveCallbacks = []
+      }
+      resolveCallbacks!.append((queue, callback))
+    }
+                          
+    return self
+  }
+  
+  public func onReject(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+                       _ callback:ErrorType?->()) -> Promise<ResolveType> {
+    objc_sync_enter(self)
+    defer { objc_sync_exit(self) }
+    switch(status) {
+    case .Resolved: break
+    case .Rejected(let err): dispatch_maybe_async(queue, block: { callback(err) })
+    case .Pending:
+      if rejectCallbacks == nil {
+        rejectCallbacks = []
+      }
+      rejectCallbacks!.append((queue, callback))
+    }
+    return self
+  }
+  
+  public func always(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+                     _ callback:Resolution<ResolveType>->()) -> Promise<ResolveType> {
+    objc_sync_enter(self)
+    defer { objc_sync_exit(self) }
+    let s = status
+    switch(s) {
+    case .Pending:
+      if alwaysCallbacks == nil {
+        alwaysCallbacks = []
+      }
+      alwaysCallbacks!.append((queue, callback))
+    default: dispatch_maybe_async(queue, block: { callback(s) })
+    }
+    return self
+  }
+  
+  public func await(timeout: NSTimeInterval?=nil) throws -> Resolution<ResolveType> {
+    switch (status) {
+    case .Pending:
+      if let timeout = timeout {
+        if dispatch_semaphore_wait(resolutionSemaphore, dispatch_time_t.fromNSTimeInterval(timeout)) != 0 {
+          throw PromiseErrors<ResolveType>.Timeout
+        }
+      } else {
+        dispatch_semaphore_wait(resolutionSemaphore, DISPATCH_TIME_FOREVER)
+      }
+    default: break
+    }
+    return status
+  }
+  
+  // Changing states
+  internal func updatedStatus() {
+    // Do reject/resolve callbacks, then always callbacks
+    let s = status
+    switch (s) {
+    case .Pending: return // Don't do anything, but this shouldn't happen
+    case .Rejected(let err):
+      guard let callbacks = rejectCallbacks else { break }
+      for (queue, callback) in callbacks {
+        dispatch_maybe_async(queue) {
+          callback(err)
+        }
+      }
+    case .Resolved(let obj):
+      guard let callbacks = resolveCallbacks else { break }
+      for (queue, callback) in callbacks {
+        dispatch_maybe_async(queue) {
+          callback(obj)
+        }
+      }
+    }
+    
+    defer { dispatch_semaphore_signal(resolutionSemaphore) }
+    guard let callbacks = alwaysCallbacks else { return }
+    for (queue, callback) in callbacks {
+      dispatch_maybe_async(queue) {
+        callback(s)
+      }
+    }
+  }
+}
+
+public class ResolvedPromise<ResolveType>: Promise<ResolveType> {
+  var resolvedObj:ResolveType
+  
+  override private init() {
+    fatalError("Cannot init this way")
+  }
+  
+  public convenience init(_ resolved: ResolveType) {
+    self.init(resolved: resolved)
+    self.resolvedObj = resolved
+    dispatch_semaphore_signal(resolutionSemaphore)
+  }
+  
+  override public func onResolve(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+    _ callback:ResolveType->()) -> Promise<ResolveType> {
+      dispatch_maybe_async(queue, block: { callback(self.resolvedObj) })
+      return self
+  }
+
+  override public func always(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+    _ callback:Resolution<ResolveType>->()) -> Promise<ResolveType> {
+      dispatch_maybe_async(queue, block: { callback(self.status) })
+      return self
+  }
+  
+  override public func resolve(obj:ResolveType) throws {
+    throw PromiseErrors<ResolveType>.AlreadyResolved(existingObj: resolvedObj)
+  }
+
+  override public func reject(err:ErrorType?) throws {
+    throw PromiseErrors<ResolveType>.AlreadyResolved(existingObj: resolvedObj)
+  }
+}
+
+public class RejectedPromise: Promise<Void> {
+  var err:ErrorType?
+  
+  override private init() {
+    fatalError("Cannot init this way")
+  }
+  
+  public convenience init(_ error: ErrorType?) {
+    self.init(rejected: error)
+    self.err = error
+    dispatch_semaphore_signal(resolutionSemaphore)
+  }
+  
+  override public func onReject(on queue: dispatch_queue_t?, _ callback: ErrorType? -> ()) -> Promise<Void> {
+    dispatch_maybe_async(queue, block: { callback(self.err) })
+    return self
+  }
+
+  override public func always(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+    _ callback:Resolution<Void>->()) -> Promise<Void> {
+    dispatch_maybe_async(queue, block: { callback(self.status) })
+    return self
+  }
+  
+  override public func resolve(obj:Void) throws {
+    throw PromiseErrors<Void>.AlreadyRejected(existingErr: self.err)
+  }
+
+  override public func reject(err:ErrorType?) throws {
+    throw PromiseErrors<Void>.AlreadyRejected(existingErr: self.err)
+  }
+}
+
+public enum Resolution<ResolveType> {
+  case Pending
+  case Resolved(obj:ResolveType)
+  case Rejected(err:ErrorType?)
+}
+
+/// Quick initializers for already resolved/rejected constructors
+public extension Promise {
+  public static func resolved() -> Promise<Void> { return Promise<Void>(resolved: ()) }
+  public static func resolved(obj:ResolveType) -> Promise<ResolveType> { return ResolvedPromise(obj) }
+  public static func rejected(err:ErrorType? = nil) -> Promise<Void> { return RejectedPromise(err) }
+}
+
+/// Chaining API
+public extension Promise {
+  func then<T>(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+               _ callback:ResolveType throws ->T) -> Promise<T> {
+    let p = Promise<T>()
+    onResolve(on: queue) { obj in
+      do {
+        let transformed = try callback(obj)
+        try p.resolve(transformed)
+      } catch let e {
+        try! p.reject(e)
+      }
+    }
+    onReject(on: queue) { err in
+      try! p.reject(err)
+    }
+    return p
+  }
+ 
+  /// Specialize then for when it returns another Promise to hook onto that automatically
+  func then<T>(on queue: dispatch_queue_t?=dispatch_get_main_queue(),
+               _ callback:ResolveType throws ->Promise<T>) -> Promise<T> {
+    let p = Promise<T>()
+                
+    onResolve(on: queue) { obj in
+      do {
+        let newPromise = try callback(obj)
+        newPromise.onResolve(on: queue) { obj in
+          do {
+            try p.resolve(obj)
+          } catch let e {
+            try! p.reject(e)
+          }
+        }
+        newPromise.onReject(on: queue) { err in
+          try! p.reject(err)
+        }
+      } catch let e {
+        try! p.reject(e)
+      }
+    }
+                
+    onReject(on: queue) { err in
+      try! p.reject(err)
+    }
+    return p
+  }
+  
+  func thenInBackground<T>(callback:ResolveType throws ->T) -> Promise<T> {
+    return then(on: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), callback)
+  }
+
+  func thenOnSameThread<T>(callback:ResolveType throws ->T) -> Promise<T> {
+    return then(on: nil, callback)
+  }
+}
+
+/// Visibility into status
+public extension Promise {
+  public func isPending() -> Bool {
+    switch (status) {
+    case .Pending: return true
+    default: return false
+    }
+  }
+  
+  public func isResolved() -> Bool {
+    switch (status) {
+    case .Resolved: return true
+    default: return false
+    }
+  }
+  
+  public func isRejected() -> Bool {
+    switch (status) {
+    case .Rejected: return true
+    default: return false
+    }
+  }
+}
+
+/// Utilities for timeout functionality
+public extension Promise {
+  /// Timeout (reject) if not resolved or rejected within a given timeframe
+  public func rejectAfterDelay(on queue:dispatch_queue_t=dispatch_get_main_queue(), delay:NSTimeInterval) {
+    dispatch_after_delay(delay, queue: queue, block: {
+      switch (self.status) {
+      case .Pending:
+        do { try self.reject(PromiseErrors<ResolveType>.Timeout) }
+        catch { }
+      default: break
+      }
+    })
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/util/Strings.swift b/lib/v23/util/Strings.swift
new file mode 100644
index 0000000..31ac9fd
--- /dev/null
+++ b/lib/v23/util/Strings.swift
@@ -0,0 +1,16 @@
+//
+//  Strings.swift
+//  v23
+//
+//  Created by Aaron Zinman on 12/1/15.
+//  Copyright © 2015 Google Inc. All rights reserved.
+//
+
+import Foundation
+
+internal extension String {
+  internal static func fromCStringNoCopy(ptr:UnsafeMutablePointer<Int8>, freeWhenDone:Bool) -> String? {
+    return String.init(bytesNoCopy: ptr, length: Int(strlen(ptr)),
+      encoding: NSUTF8StringEncoding, freeWhenDone: true)
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/util/Threads.swift b/lib/v23/util/Threads.swift
new file mode 100644
index 0000000..c2c3c6d
--- /dev/null
+++ b/lib/v23/util/Threads.swift
@@ -0,0 +1,57 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+import Foundation
+
+internal func dispatch_maybe_async(queue:dispatch_queue_t?, block:dispatch_block_t) {
+  guard let queue = queue else {
+    block()
+    return
+  }
+  if (isCurrentQueue(queue)) {
+    block()
+  } else {
+    dispatch_async(queue, block)
+  }
+}
+
+internal func dispatch_maybe_sync(queue:dispatch_queue_t?, block:dispatch_block_t) {
+  guard let queue = queue else {
+    block()
+    return
+  }
+  if (isCurrentQueue(queue)) {
+    block()
+  } else {
+    dispatch_sync(queue, block)
+  }
+}
+
+internal func isCurrentQueue(queue:dispatch_queue_t) -> Bool {
+  let current = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
+  let queueName = dispatch_queue_get_label(queue)
+  return current != nil && queueName != nil && strcmp(current, queueName) == 0
+}
+
+internal func dispatch_after_delay(delay:NSTimeInterval, queue:dispatch_queue_t, block:dispatch_block_t) {
+  dispatch_after(dispatch_time_t.fromNSTimeInterval(delay), queue, block)
+}
+
+internal func RunOnMain(block:dispatch_block_t) {
+  dispatch_maybe_async(dispatch_get_main_queue(), block: block)
+}
+
+internal func RunInBackground(block:dispatch_block_t) {
+  dispatch_maybe_async(dispatch_get_bg_queue(), block: block)
+}
+
+internal func dispatch_get_bg_queue() -> dispatch_queue_t {
+  return dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)
+}
+
+extension dispatch_time_t {
+  static func fromNSTimeInterval(t:NSTimeInterval) -> dispatch_time_t {
+    return dispatch_time(DISPATCH_TIME_NOW, Int64(t * Double(NSEC_PER_SEC)))
+  }
+}
\ No newline at end of file
diff --git a/lib/v23/v23.h b/lib/v23/v23.h
new file mode 100644
index 0000000..82c7bab
--- /dev/null
+++ b/lib/v23/v23.h
@@ -0,0 +1,17 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#import <UIKit/UIKit.h>
+
+//! Project version number for v23.
+FOUNDATION_EXPORT double v23VersionNumber;
+
+//! Project version string for v23.
+FOUNDATION_EXPORT const unsigned char v23VersionString[];
+
+// Generated Go headers
+#import <v23/ios.h>
+#import <v23/context.h>
+#import <v23/rt.h>
+#import <v23/rpc.h>
\ No newline at end of file
diff --git a/lib/v23Tests/Info.plist b/lib/v23Tests/Info.plist
new file mode 100644
index 0000000..ba72822
--- /dev/null
+++ b/lib/v23Tests/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/lib/v23Tests/PromiseTests.swift b/lib/v23Tests/PromiseTests.swift
new file mode 100644
index 0000000..6a14c92
--- /dev/null
+++ b/lib/v23Tests/PromiseTests.swift
@@ -0,0 +1,131 @@
+//
+//  PromiseTests.swift
+//  v23
+//
+//  Created by Aaron Zinman on 11/30/15.
+//  Copyright © 2015 Google Inc. All rights reserved.
+//
+
+import XCTest
+import v23
+
+enum TestErrors : ErrorType {
+  case SomeError
+  case SomeOtherError
+}
+
+class PromiseTests: XCTestCase {
+  func testBasicResolution() {
+    var alwaysRan = false
+    let p = v23.Promise<Int>()
+      .onResolve { obj in XCTAssertEqual(obj, 5) }
+      .onReject { err in XCTFail("Shouldn't have gotten \(err)") }
+      .always { status in
+        switch (status) {
+        case .Pending: XCTFail("Can't get pending in always")
+        case .Rejected(let e): XCTFail("Shouldn't have gotten \(e)")
+        case .Resolved: alwaysRan = true
+        }
+      }
+    try! p.resolve(5)
+    XCTAssertTrue(alwaysRan)
+    
+    var ranNow = false
+    p.onResolve { obj in
+      ranNow = true
+    }
+    XCTAssertTrue(ranNow)
+  }
+
+  func testBasicRejection() {
+    var alwaysRan = false
+    let p = v23.Promise<Int>()
+      .onResolve { obj in XCTFail("Shouldn't have gotten \(obj)") }
+      .onReject { err in
+        guard let e = err else { XCTFail("Invalid nil error"); return }
+        switch(e) {
+        case TestErrors.SomeError: break
+        default: XCTFail("Shouldn't have gotten this error \(e)")
+        }
+      }
+      .always { status in
+        switch (status) {
+        case .Pending: XCTFail("Can't get pending in always")
+        case .Rejected: alwaysRan = true
+        case .Resolved(let o): XCTFail("Shouldn't have gotten \(o)")
+        }
+      }
+    try! p.reject(TestErrors.SomeError)
+    XCTAssertTrue(alwaysRan)
+
+    var ranNow = false
+    p.onReject { err in
+      ranNow = true
+    }
+    XCTAssertTrue(ranNow)
+  }
+
+  func testResolutionDoesntRunOnResolve() {
+    let p = v23.Promise<Int>()
+    p.onResolve { obj in
+      XCTFail("Shouldn't have gotten \(obj)")
+    }
+    try! p.reject(TestErrors.SomeError)
+  }
+  
+  func testRejectionDoesntRunOnResolve() {
+    let p = v23.Promise<Int>()
+    p.onReject { err in
+      XCTFail("Shouldn't have gotten \(err)")
+    }
+    try! p.resolve(5)
+  }
+  
+  func testThenTransforms() {
+    let p = v23.Promise<Int>()
+    try! p.resolve(5)
+    
+    var finalResult:String = ""
+    p.then { obj -> String in
+      XCTAssertEqual(obj, 5)
+      return "hello"
+    }.onResolve { obj in
+      XCTAssertEqual(obj, "hello")
+      finalResult = obj
+    }
+    XCTAssertEqual(finalResult, "hello")
+  }
+
+  func testThenPropagatesError() {
+    let p = v23.Promise<Int>()
+    
+    var didReject = false
+    p.then { obj -> String in
+      XCTAssertEqual(obj, 5)
+      return "hello"
+    }.onReject { _ in
+      didReject = true
+    }
+    try! p.reject(TestErrors.SomeError)
+    XCTAssertTrue(didReject)
+  }
+  
+  func testThenReturningPromiseWorks() {
+    let p = v23.Promise<Int>()
+    let bgQueue = dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)
+    let finalP = p.then(on: bgQueue) { x -> Promise<Int> in
+      let newP = v23.Promise<Int>()
+      dispatch_async(bgQueue) {
+        try! newP.resolve(x + 10)
+      }
+      return newP
+    }
+    
+    try! p.resolve(5)
+    let finalStatus = try! finalP.await()
+    switch (finalStatus) {
+    case .Resolved(let v): XCTAssertEqual(v, 15)
+    default: XCTFail("Supposed to be resolved")
+    }
+  }
+}
diff --git a/lib/v23Tests/v23Tests.swift b/lib/v23Tests/v23Tests.swift
new file mode 100644
index 0000000..9f46aa7
--- /dev/null
+++ b/lib/v23Tests/v23Tests.swift
@@ -0,0 +1,19 @@
+//
+//  v23Tests.swift
+//  v23Tests
+//
+//  Created by Aaron Zinman on 11/12/15.
+//  Copyright © 2015 Google Inc. All rights reserved.
+//
+
+import XCTest
+@testable import v23
+
+class v23Tests: XCTestCase {
+    func testInit() {
+      // Currently this fails because of environmental flags passed by the Unit Test framework
+      // that Vanadium ends up reading in and barfing on. Need to solve at some point.
+      try! v23.V23.configure()
+      let instance = v23.V23.instance
+    }
+}