aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--INSTALL5
-rw-r--r--Makefile68
-rw-r--r--README.md16
-rw-r--r--build.json4
-rw-r--r--src/core/channel/client_setup.c29
-rw-r--r--src/core/channel/client_setup.h6
-rw-r--r--src/core/surface/channel_create.c5
-rw-r--r--src/core/surface/secure_channel_create.c5
-rw-r--r--src/node/index.js33
-rw-r--r--src/node/interop/interop_client.js62
-rw-r--r--src/node/interop/messages.proto10
-rw-r--r--src/node/package.json3
-rw-r--r--src/node/src/client.js193
-rw-r--r--src/node/test/interop_sanity_test.js21
-rw-r--r--src/objective-c/.gitignore18
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.h90
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.m406
-rw-r--r--src/objective-c/GRPCClient/GRPCMethodName.h48
-rw-r--r--src/objective-c/GRPCClient/GRPCMethodName.m47
-rw-r--r--src/objective-c/GRPCClient/README.md4
-rw-r--r--src/objective-c/GRPCClient/private/GRPCChannel.h50
-rw-r--r--src/objective-c/GRPCClient/private/GRPCChannel.m65
-rw-r--r--src/objective-c/GRPCClient/private/GRPCCompletionQueue.h54
-rw-r--r--src/objective-c/GRPCClient/private/GRPCCompletionQueue.m106
-rw-r--r--src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h81
-rw-r--r--src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m120
-rw-r--r--src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h40
-rw-r--r--src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m44
-rw-r--r--src/objective-c/GRPCClient/private/NSData+GRPC.h41
-rw-r--r--src/objective-c/GRPCClient/private/NSData+GRPC.m86
-rw-r--r--src/objective-c/GRPCClient/private/NSDictionary+GRPC.h40
-rw-r--r--src/objective-c/GRPCClient/private/NSDictionary+GRPC.m56
-rw-r--r--src/objective-c/GRPCClient/private/NSError+GRPC.h74
-rw-r--r--src/objective-c/GRPCClient/private/NSError+GRPC.m51
-rw-r--r--src/objective-c/README.md3
-rw-r--r--src/objective-c/RxLibrary/GRXImmediateWriter.h73
-rw-r--r--src/objective-c/RxLibrary/GRXImmediateWriter.m165
-rw-r--r--src/objective-c/RxLibrary/GRXWriteable.h60
-rw-r--r--src/objective-c/RxLibrary/GRXWriteable.m66
-rw-r--r--src/objective-c/RxLibrary/GRXWriter+Immediate.h66
-rw-r--r--src/objective-c/RxLibrary/GRXWriter+Immediate.m64
-rw-r--r--src/objective-c/RxLibrary/GRXWriter+Transformations.h42
-rw-r--r--src/objective-c/RxLibrary/GRXWriter+Transformations.m47
-rw-r--r--src/objective-c/RxLibrary/GRXWriter.h127
-rw-r--r--src/objective-c/RxLibrary/GRXWriter.m112
-rw-r--r--src/objective-c/RxLibrary/NSEnumerator+GRXUtil.h51
-rw-r--r--src/objective-c/RxLibrary/NSEnumerator+GRXUtil.m54
-rw-r--r--src/objective-c/RxLibrary/README.md8
-rw-r--r--src/objective-c/RxLibrary/RxLibrary.podspec13
-rw-r--r--src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.h42
-rw-r--r--src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.m61
-rw-r--r--src/objective-c/RxLibrary/private/GRXNSFastEnumerator.h43
-rw-r--r--src/objective-c/RxLibrary/private/GRXNSFastEnumerator.m88
-rw-r--r--src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.h41
-rw-r--r--src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.m57
-rw-r--r--src/objective-c/RxLibrary/transformations/GRXMappingWriter.h40
-rw-r--r--src/objective-c/RxLibrary/transformations/GRXMappingWriter.m63
-rw-r--r--src/objective-c/examples/Sample/Podfile12
-rw-r--r--src/objective-c/examples/Sample/Podfile.lock14
l---------src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXImmediateWriter.h1
l---------src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXMappingWriter.h1
l---------src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriteable.h1
l---------src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Immediate.h1
l---------src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Transformations.h1
l---------src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter.h1
l---------src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/NSEnumerator+GRXUtil.h1
-rw-r--r--src/objective-c/examples/Sample/Pods/Local Podspecs/RxLibrary.podspec13
-rw-r--r--src/objective-c/examples/Sample/Pods/Manifest.lock14
-rw-r--r--src/objective-c/examples/Sample/Pods/Pods.xcodeproj/project.pbxproj2888
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-Private.xcconfig5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-dummy.m5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-prefix.pch5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary.xcconfig0
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-Private.xcconfig5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-dummy.m5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary.xcconfig0
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.markdown3
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.plist29
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-dummy.m5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-environment.h14
-rwxr-xr-xsrc/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh74
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig6
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig6
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-Private.xcconfig5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-dummy.m5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary.xcconfig0
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.markdown3
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.plist29
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-dummy.m5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-environment.h14
-rwxr-xr-xsrc/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-resources.sh74
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.debug.xcconfig6
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.release.xcconfig6
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown3
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.plist29
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-dummy.m5
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-environment.h14
-rwxr-xr-xsrc/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-resources.sh74
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.debug.xcconfig6
-rw-r--r--src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.release.xcconfig6
-rw-r--r--src/objective-c/examples/Sample/README.md2
-rw-r--r--src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj955
-rw-r--r--src/objective-c/examples/Sample/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--src/objective-c/examples/Sample/Sample.xcworkspace/contents.xcworkspacedata10
-rw-r--r--src/objective-c/examples/Sample/Sample/AppDelegate.h42
-rw-r--r--src/objective-c/examples/Sample/Sample/AppDelegate.m70
-rw-r--r--src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib41
-rw-r--r--src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard25
-rw-r--r--src/objective-c/examples/Sample/Sample/Images.xcassets/AppIcon.appiconset/Contents.json68
-rw-r--r--src/objective-c/examples/Sample/Sample/Info.plist47
-rw-r--r--src/objective-c/examples/Sample/Sample/ViewController.h40
-rw-r--r--src/objective-c/examples/Sample/Sample/ViewController.m52
-rw-r--r--src/objective-c/examples/Sample/Sample/main.m41
-rw-r--r--src/objective-c/examples/Sample/SampleTests/Info.plist24
-rw-r--r--src/objective-c/examples/Sample/SampleTests/SampleTests.m65
-rw-r--r--templates/Makefile.template70
-rw-r--r--tools/dockerfile/grpc_node/Dockerfile7
-rwxr-xr-xtools/gce_setup/grpc_docker.sh30
-rwxr-xr-xtools/gce_setup/shared_startup_funcs.sh4
121 files changed, 8214 insertions, 157 deletions
diff --git a/INSTALL b/INSTALL
index f1e7aa7bf4..2f5f29c788 100644
--- a/INSTALL
+++ b/INSTALL
@@ -23,6 +23,11 @@ Building the python wrapper requires the following:
# apt-get install python-all-dev python-virtualenv
+If you want to install in a different directory than the default /usr/lib, you can
+override it on the command line:
+
+ # make install prefix=/opt
+
*******************************
* More detailled instructions *
diff --git a/Makefile b/Makefile
index 68d56a06a4..a1b8fbbbc5 100644
--- a/Makefile
+++ b/Makefile
@@ -332,9 +332,9 @@ endif
.SECONDARY = %.pb.h %.pb.cc
-PROTOC_PLUGINS= $(BINDIR)/$(CONFIG)/cpp_plugin $(BINDIR)/$(CONFIG)/ruby_plugin
+PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
ifeq ($(DEP_MISSING),)
-all: static shared
+all: static shared plugins
dep_error:
@echo "You shouldn't see this message - all of your dependencies are correct."
else
@@ -498,7 +498,7 @@ timeout_encoding_test: $(BINDIR)/$(CONFIG)/timeout_encoding_test
transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test
async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
-cpp_plugin: $(BINDIR)/$(CONFIG)/cpp_plugin
+grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin
credentials_test: $(BINDIR)/$(CONFIG)/credentials_test
end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
interop_client: $(BINDIR)/$(CONFIG)/interop_client
@@ -508,7 +508,7 @@ pubsub_publisher_test: $(BINDIR)/$(CONFIG)/pubsub_publisher_test
pubsub_subscriber_test: $(BINDIR)/$(CONFIG)/pubsub_subscriber_test
qps_client: $(BINDIR)/$(CONFIG)/qps_client
qps_server: $(BINDIR)/$(CONFIG)/qps_server
-ruby_plugin: $(BINDIR)/$(CONFIG)/ruby_plugin
+grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
status_test: $(BINDIR)/$(CONFIG)/status_test
thread_pool_test: $(BINDIR)/$(CONFIG)/thread_pool_test
chttp2_fake_security_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test
@@ -905,6 +905,8 @@ shared_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT)
shared_csharp: shared_c $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT)
grpc_csharp_ext: shared_csharp
+plugins: $(PROTOC_PLUGINS)
+
privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack_uds.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a $(LIBDIR)/$(CONFIG)/libend2end_test_empty_batch.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a
@@ -1912,7 +1914,7 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
-install: install_c install_cxx
+install: install_c install_cxx install-protobuf install-plugins
install_c: install-headers_c install-static_c install-shared_c
@@ -1946,6 +1948,8 @@ install-static_cxx: static_cxx strip-static_cxx
$(E) "[INSTALL] Installing libgrpc++.a"
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(prefix)/lib/libgrpc++.a
+
+
install-shared_c: shared_c strip-shared_c
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing gpr.$(SHARED_EXT)"
@@ -1986,7 +1990,8 @@ ifneq ($(SYSTEM),Darwin)
endif
endif
-install-shared_cxx: shared_cxx strip-shared_cxx
+
+install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing grpc++.$(SHARED_EXT)"
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT) $(prefix)/lib/grpc++.$(SHARED_EXT)
@@ -2004,6 +2009,7 @@ ifneq ($(SYSTEM),Darwin)
endif
endif
+
install-shared_csharp: shared_csharp strip-shared_csharp
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing grpc_csharp_ext.$(SHARED_EXT)"
@@ -2022,7 +2028,29 @@ ifneq ($(SYSTEM),Darwin)
endif
endif
+
+install-protobuf: $(PROTOBUF_DEP)
+ifneq ($(PROTOBUF_DEP),)
+ $(E) "[INSTALL] Installing embedded protobufs"
+ $(Q) $(MAKE) -C third_party/protobuf install prefix=$(prefix)
+ifneq ($(SYSTEM),MINGW32)
+ifneq ($(SYSTEM),Darwin)
+ $(Q) ldconfig
+endif
+endif
+endif
+
+install-plugins: $(PROTOC_PLUGINS)
+ifeq ($(SYSTEM),MINGW32)
+ $(Q) false
+else
+ $(E) "[INSTALL] Installing grpc protoc plugins"
+ $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin
+ $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(prefix)/bin/grpc_ruby_plugin
+endif
+
clean:
+ $(E) "[CLEAN] Cleaning build directories."
$(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR)
@@ -7344,35 +7372,35 @@ endif
endif
-CPP_PLUGIN_SRC = \
+GRPC_CPP_PLUGIN_SRC = \
src/compiler/cpp_generator.cc \
src/compiler/cpp_plugin.cc \
-CPP_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CPP_PLUGIN_SRC))))
+GRPC_CPP_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CPP_PLUGIN_SRC))))
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins if you don't have protobuf 3.0.0+.
-$(BINDIR)/$(CONFIG)/cpp_plugin: protobuf_dep_error
+$(BINDIR)/$(CONFIG)/grpc_cpp_plugin: protobuf_dep_error
else
-$(BINDIR)/$(CONFIG)/cpp_plugin: $(PROTOBUF_DEP) $(CPP_PLUGIN_OBJS)
+$(BINDIR)/$(CONFIG)/grpc_cpp_plugin: $(PROTOBUF_DEP) $(GRPC_CPP_PLUGIN_OBJS)
$(E) "[HOSTLD] Linking $@"
$(Q) mkdir -p `dirname $@`
- $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(CPP_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/cpp_plugin
+ $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_CPP_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_cpp_plugin
endif
$(OBJDIR)/$(CONFIG)/src/compiler/cpp_generator.o:
$(OBJDIR)/$(CONFIG)/src/compiler/cpp_plugin.o:
-deps_cpp_plugin: $(CPP_PLUGIN_OBJS:.o=.dep)
+deps_grpc_cpp_plugin: $(GRPC_CPP_PLUGIN_OBJS:.o=.dep)
ifneq ($(NO_DEPS),true)
--include $(CPP_PLUGIN_OBJS:.o=.dep)
+-include $(GRPC_CPP_PLUGIN_OBJS:.o=.dep)
endif
@@ -7671,35 +7699,35 @@ endif
endif
-RUBY_PLUGIN_SRC = \
+GRPC_RUBY_PLUGIN_SRC = \
src/compiler/ruby_generator.cc \
src/compiler/ruby_plugin.cc \
-RUBY_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RUBY_PLUGIN_SRC))))
+GRPC_RUBY_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_RUBY_PLUGIN_SRC))))
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins if you don't have protobuf 3.0.0+.
-$(BINDIR)/$(CONFIG)/ruby_plugin: protobuf_dep_error
+$(BINDIR)/$(CONFIG)/grpc_ruby_plugin: protobuf_dep_error
else
-$(BINDIR)/$(CONFIG)/ruby_plugin: $(PROTOBUF_DEP) $(RUBY_PLUGIN_OBJS)
+$(BINDIR)/$(CONFIG)/grpc_ruby_plugin: $(PROTOBUF_DEP) $(GRPC_RUBY_PLUGIN_OBJS)
$(E) "[HOSTLD] Linking $@"
$(Q) mkdir -p `dirname $@`
- $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(RUBY_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/ruby_plugin
+ $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_RUBY_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
endif
$(OBJDIR)/$(CONFIG)/src/compiler/ruby_generator.o:
$(OBJDIR)/$(CONFIG)/src/compiler/ruby_plugin.o:
-deps_ruby_plugin: $(RUBY_PLUGIN_OBJS:.o=.dep)
+deps_grpc_ruby_plugin: $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep)
ifneq ($(NO_DEPS),true)
--include $(RUBY_PLUGIN_OBJS:.o=.dep)
+-include $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep)
endif
diff --git a/README.md b/README.md
index 99e19db337..2b049d206b 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,22 @@ Copyright 2015 Google Inc.
See grpc/INSTALL for installation instructions for various platforms.
+#Repository Structure
+
+This repository contains source code for gRPC libraries for multiple lanugages written on top
+of shared C core library [src/core] (src/core).
+
+ * C++ source code: [src/cpp] (src/cpp)
+ * Python source code: [src/python] (src/python)
+ * Ruby source code: [src/ruby] (src/ruby)
+ * NodeJS source code: [src/node] (src/node)
+ * PHP source code: [src/php] (src/php)
+ * C# source code: [src/csharp] (src/csharp)
+
+Java source code is in [grpc-java] (http://github.com/grpc/grpc-java) repository.
+Go source code is in [grpc-go] (http://github.com/grpc/grpc-go) repository.
+
+
#Overview
diff --git a/build.json b/build.json
index 018322ff53..47f00a27e8 100644
--- a/build.json
+++ b/build.json
@@ -1574,7 +1574,7 @@
]
},
{
- "name": "cpp_plugin",
+ "name": "grpc_cpp_plugin",
"build": "protoc",
"language": "c++",
"headers": [
@@ -1746,7 +1746,7 @@
]
},
{
- "name": "ruby_plugin",
+ "name": "grpc_ruby_plugin",
"build": "protoc",
"language": "c++",
"src": [
diff --git a/src/core/channel/client_setup.c b/src/core/channel/client_setup.c
index bb6d363807..6d892d6c92 100644
--- a/src/core/channel/client_setup.c
+++ b/src/core/channel/client_setup.c
@@ -49,8 +49,11 @@ struct grpc_client_setup {
grpc_alarm backoff_alarm;
gpr_timespec current_backoff_interval;
int in_alarm;
+ int in_cb;
+ int cancelled;
gpr_mu mu;
+ gpr_cv cv;
grpc_client_setup_request *active_request;
int refs;
};
@@ -67,6 +70,7 @@ gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r) {
static void destroy_setup(grpc_client_setup *s) {
gpr_mu_destroy(&s->mu);
+ gpr_cv_destroy(&s->cv);
s->done(s->user_data);
grpc_channel_args_destroy(s->args);
gpr_free(s);
@@ -111,6 +115,10 @@ static void setup_cancel(grpc_transport_setup *sp) {
int cancel_alarm = 0;
gpr_mu_lock(&s->mu);
+ s->cancelled = 1;
+ while (s->in_cb) {
+ gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
+ }
GPR_ASSERT(s->refs > 0);
/* effectively cancels the current request (if any) */
@@ -129,6 +137,24 @@ static void setup_cancel(grpc_transport_setup *sp) {
}
}
+int grpc_client_setup_cb_begin(grpc_client_setup_request *r) {
+ gpr_mu_lock(&r->setup->mu);
+ if (r->setup->cancelled) {
+ gpr_mu_unlock(&r->setup->mu);
+ return 0;
+ }
+ r->setup->in_cb++;
+ gpr_mu_unlock(&r->setup->mu);
+ return 1;
+}
+
+void grpc_client_setup_cb_end(grpc_client_setup_request *r) {
+ gpr_mu_lock(&r->setup->mu);
+ r->setup->in_cb--;
+ if (r->setup->cancelled) gpr_cv_signal(&r->setup->cv);
+ gpr_mu_unlock(&r->setup->mu);
+}
+
/* vtable for transport setup */
static const grpc_transport_setup_vtable setup_vtable = {setup_initiate,
setup_cancel};
@@ -142,6 +168,7 @@ void grpc_client_setup_create_and_attach(
s->base.vtable = &setup_vtable;
gpr_mu_init(&s->mu);
+ gpr_cv_init(&s->cv);
s->refs = 1;
s->mdctx = mdctx;
s->initiate = initiate;
@@ -151,6 +178,8 @@ void grpc_client_setup_create_and_attach(
s->args = grpc_channel_args_copy(args);
s->current_backoff_interval = gpr_time_from_micros(1000000);
s->in_alarm = 0;
+ s->in_cb = 0;
+ s->cancelled = 0;
grpc_client_channel_set_transport_setup(newly_minted_channel, &s->base);
}
diff --git a/src/core/channel/client_setup.h b/src/core/channel/client_setup.h
index 6ac3fe62f1..f2b64265bc 100644
--- a/src/core/channel/client_setup.h
+++ b/src/core/channel/client_setup.h
@@ -58,6 +58,12 @@ void grpc_client_setup_request_finish(grpc_client_setup_request *r,
const grpc_channel_args *grpc_client_setup_get_channel_args(
grpc_client_setup_request *r);
+/* Call before calling back into the setup listener, and call only if
+ this function returns 1. If it returns 1, also promise to call
+ grpc_client_setup_cb_end */
+int grpc_client_setup_cb_begin(grpc_client_setup_request *r);
+void grpc_client_setup_cb_end(grpc_client_setup_request *r);
+
/* Get the deadline for a request passed in to initiate. Implementations should
make a best effort to honor this deadline. */
gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r);
diff --git a/src/core/surface/channel_create.c b/src/core/surface/channel_create.c
index 7a5f62ed53..3104b1d00d 100644
--- a/src/core/surface/channel_create.c
+++ b/src/core/surface/channel_create.c
@@ -107,13 +107,16 @@ static void on_connect(void *rp, grpc_endpoint *tcp) {
} else {
return;
}
- } else {
+ } else if (grpc_client_setup_cb_begin(r->cs_request)) {
grpc_create_chttp2_transport(
r->setup->setup_callback, r->setup->setup_user_data,
grpc_client_setup_get_channel_args(r->cs_request), tcp, NULL, 0,
grpc_client_setup_get_mdctx(r->cs_request), 1);
+ grpc_client_setup_cb_end(r->cs_request);
done(r, 1);
return;
+ } else {
+ done(r, 0);
}
}
diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c
index c6968f4b24..8e56868d42 100644
--- a/src/core/surface/secure_channel_create.c
+++ b/src/core/surface/secure_channel_create.c
@@ -97,12 +97,15 @@ static void on_secure_transport_setup_done(void *rp,
if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
done(r, 0);
- } else {
+ } else if (grpc_client_setup_cb_begin(r->cs_request)) {
grpc_create_chttp2_transport(
r->setup->setup_callback, r->setup->setup_user_data,
grpc_client_setup_get_channel_args(r->cs_request), secure_endpoint,
NULL, 0, grpc_client_setup_get_mdctx(r->cs_request), 1);
+ grpc_client_setup_cb_end(r->cs_request);
done(r, 1);
+ } else {
+ done(r, 0);
}
}
diff --git a/src/node/index.js b/src/node/index.js
index fe1fb1d399..1bef2072dd 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -74,6 +74,37 @@ function load(filename) {
}
/**
+ * Get a function that a client can use to update metadata with authentication
+ * information from a Google Auth credential object, which comes from the
+ * googleauth library.
+ * @param {Object} credential The credential object to use
+ * @return {function(Object, callback)} Metadata updater function
+ */
+function getGoogleAuthDelegate(credential) {
+ /**
+ * Update a metadata object with authentication information.
+ * @param {Object} metadata Metadata object
+ * @param {function(Error, Object)} callback
+ */
+ return function updateMetadata(metadata, callback) {
+ metadata = _.clone(metadata);
+ if (metadata.Authorization) {
+ metadata.Authorization = _.clone(metadata.Authorization);
+ } else {
+ metadata.Authorization = [];
+ }
+ credential.getAccessToken(function(err, token) {
+ if (err) {
+ callback(err);
+ return;
+ }
+ metadata.Authorization.push('Bearer ' + token);
+ callback(null, metadata);
+ });
+ };
+}
+
+/**
* See docs for loadObject
*/
exports.loadObject = loadObject;
@@ -106,3 +137,5 @@ exports.Credentials = grpc.Credentials;
* ServerCredentials factories
*/
exports.ServerCredentials = grpc.ServerCredentials;
+
+exports.getGoogleAuthDelegate = getGoogleAuthDelegate;
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index d00724b247..fc2fdf4dc9 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -35,9 +35,14 @@ var fs = require('fs');
var path = require('path');
var grpc = require('..');
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
+var GoogleAuth = require('googleauth');
var assert = require('assert');
+var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
+var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
+var AUTH_USER = '155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk@developer.gserviceaccount.com';
+
/**
* Create a buffer filled with size zeroes
* @param {number} size The length of the buffer
@@ -256,6 +261,45 @@ function cancelAfterFirstResponse(client, done) {
}
/**
+ * Run one of the authentication tests.
+ * @param {Client} client The client to test against
+ * @param {function} done Callback to call when the test is completed. Included
+ * primarily for use with mocha
+ */
+function authTest(client, done) {
+ (new GoogleAuth()).getApplicationDefault(function(err, credential) {
+ assert.ifError(err);
+ if (credential.createScopedRequired()) {
+ credential = credential.createScoped(AUTH_SCOPE);
+ }
+ client.updateMetadata = grpc.getGoogleAuthDelegate(credential);
+ var arg = {
+ response_type: testProto.PayloadType.COMPRESSABLE,
+ response_size: 314159,
+ payload: {
+ body: zeroBuffer(271828)
+ },
+ fill_username: true,
+ fill_oauth_scope: true
+ };
+ var call = client.unaryCall(arg, function(err, resp) {
+ assert.ifError(err);
+ assert.strictEqual(resp.payload.type, testProto.PayloadType.COMPRESSABLE);
+ assert.strictEqual(resp.payload.body.limit - resp.payload.body.offset,
+ 314159);
+ assert.strictEqual(resp.username, AUTH_USER);
+ assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
+ });
+ call.on('status', function(status) {
+ assert.strictEqual(status.code, grpc.status.OK);
+ if (done) {
+ done();
+ }
+ });
+ });
+}
+
+/**
* Map from test case names to test functions
*/
var test_cases = {
@@ -266,7 +310,9 @@ var test_cases = {
ping_pong: pingPong,
empty_stream: emptyStream,
cancel_after_begin: cancelAfterBegin,
- cancel_after_first_response: cancelAfterFirstResponse
+ cancel_after_first_response: cancelAfterFirstResponse,
+ compute_engine_creds: authTest,
+ service_account_creds: authTest
};
/**
@@ -280,11 +326,16 @@ var test_cases = {
* @param {function} done Callback to call when the test is completed. Included
* primarily for use with mocha
*/
-function runTest(address, host_override, test_case, tls, done) {
+function runTest(address, host_override, test_case, tls, test_ca, done) {
// TODO(mlumish): enable TLS functionality
var options = {};
if (tls) {
- var ca_path = path.join(__dirname, '../test/data/ca.pem');
+ var ca_path;
+ if (test_ca) {
+ ca_path = path.join(__dirname, '../test/data/ca.pem');
+ } else {
+ ca_path = process.env.SSL_CERT_FILE;
+ }
var ca_data = fs.readFileSync(ca_path);
var creds = grpc.Credentials.createSsl(ca_data);
options.credentials = creds;
@@ -304,7 +355,10 @@ if (require.main === module) {
'use_tls', 'use_test_ca']
});
runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
- argv.test_case, argv.use_tls === 'true');
+ argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
+ function () {
+ console.log('OK:', argv.test_case);
+ });
}
/**
diff --git a/src/node/interop/messages.proto b/src/node/interop/messages.proto
index eb6526463d..65a8140465 100644
--- a/src/node/interop/messages.proto
+++ b/src/node/interop/messages.proto
@@ -66,6 +66,12 @@ message SimpleRequest {
// Optional input payload sent along with the request.
optional Payload payload = 3;
+
+ // Whether SimpleResponse should include username.
+ optional bool fill_username = 4;
+
+ // Whether SimpleResponse should include OAuth scope.
+ optional bool fill_oauth_scope = 5;
}
// Unary response, as configured by the request.
@@ -74,7 +80,9 @@ message SimpleResponse {
optional Payload payload = 1;
// The user the request came from, for verifying authentication was
// successful when the client expected it.
- optional int64 effective_gaia_user_id = 2;
+ optional string username = 2;
+ // OAuth scope.
+ optional string oauth_scope = 3;
}
// Client-streaming request.
diff --git a/src/node/package.json b/src/node/package.json
index 8f81014c1e..821641ce19 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -14,7 +14,8 @@
},
"devDependencies": {
"mocha": "~1.21.0",
- "minimist": "^1.1.0"
+ "minimist": "^1.1.0",
+ "googleauth": "google/google-auth-library-nodejs"
},
"main": "index.js"
}
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 81fa65eb26..19c3144c7d 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -224,25 +224,32 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
emitter.cancel = function cancel() {
call.cancel();
};
- var client_batch = {};
- client_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
- client_batch[grpc.opType.SEND_MESSAGE] = serialize(argument);
- client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
- client_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
- client_batch[grpc.opType.RECV_MESSAGE] = true;
- client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
- call.startBatch(client_batch, function(err, response) {
- if (err) {
- callback(err);
+ this.updateMetadata(metadata, function(error, metadata) {
+ if (error) {
+ call.cancel();
+ callback(error);
return;
}
- if (response.status.code != grpc.status.OK) {
- callback(response.status);
- return;
- }
- emitter.emit('status', response.status);
- emitter.emit('metadata', response.metadata);
- callback(null, deserialize(response.read));
+ var client_batch = {};
+ client_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
+ client_batch[grpc.opType.SEND_MESSAGE] = serialize(argument);
+ client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
+ client_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
+ client_batch[grpc.opType.RECV_MESSAGE] = true;
+ client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
+ call.startBatch(client_batch, function(err, response) {
+ if (err) {
+ callback(err);
+ return;
+ }
+ if (response.status.code != grpc.status.OK) {
+ callback(response.status);
+ return;
+ }
+ emitter.emit('status', response.status);
+ emitter.emit('metadata', response.metadata);
+ callback(null, deserialize(response.read));
+ });
});
return emitter;
}
@@ -279,30 +286,37 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
metadata = {};
}
var stream = new ClientWritableStream(call, serialize);
- var metadata_batch = {};
- metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
- metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
- call.startBatch(metadata_batch, function(err, response) {
- if (err) {
- callback(err);
- return;
- }
- stream.emit('metadata', response.metadata);
- });
- var client_batch = {};
- client_batch[grpc.opType.RECV_MESSAGE] = true;
- client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
- call.startBatch(client_batch, function(err, response) {
- if (err) {
- callback(err);
- return;
- }
- if (response.status.code != grpc.status.OK) {
- callback(response.status);
+ this.updateMetadata(metadata, function(error, metadata) {
+ if (error) {
+ call.cancel();
+ callback(error);
return;
}
- stream.emit('status', response.status);
- callback(null, deserialize(response.read));
+ var metadata_batch = {};
+ metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
+ metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
+ call.startBatch(metadata_batch, function(err, response) {
+ if (err) {
+ callback(err);
+ return;
+ }
+ stream.emit('metadata', response.metadata);
+ });
+ var client_batch = {};
+ client_batch[grpc.opType.RECV_MESSAGE] = true;
+ client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
+ call.startBatch(client_batch, function(err, response) {
+ if (err) {
+ callback(err);
+ return;
+ }
+ if (response.status.code != grpc.status.OK) {
+ callback(response.status);
+ return;
+ }
+ stream.emit('status', response.status);
+ callback(null, deserialize(response.read));
+ });
});
return stream;
}
@@ -339,24 +353,31 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
metadata = {};
}
var stream = new ClientReadableStream(call, deserialize);
- var start_batch = {};
- start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
- start_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
- start_batch[grpc.opType.SEND_MESSAGE] = serialize(argument);
- start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
- call.startBatch(start_batch, function(err, response) {
- if (err) {
- throw err;
- }
- stream.emit('metadata', response.metadata);
- });
- var status_batch = {};
- status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
- call.startBatch(status_batch, function(err, response) {
- if (err) {
- throw err;
+ this.updateMetadata(metadata, function(error, metadata) {
+ if (error) {
+ call.cancel();
+ stream.emit('error', error);
+ return;
}
- stream.emit('status', response.status);
+ var start_batch = {};
+ start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
+ start_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
+ start_batch[grpc.opType.SEND_MESSAGE] = serialize(argument);
+ start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
+ call.startBatch(start_batch, function(err, response) {
+ if (err) {
+ throw err;
+ }
+ stream.emit('metadata', response.metadata);
+ });
+ var status_batch = {};
+ status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
+ call.startBatch(status_batch, function(err, response) {
+ if (err) {
+ throw err;
+ }
+ stream.emit('status', response.status);
+ });
});
return stream;
}
@@ -391,22 +412,29 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
metadata = {};
}
var stream = new ClientDuplexStream(call, serialize, deserialize);
- var start_batch = {};
- start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
- start_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
- call.startBatch(start_batch, function(err, response) {
- if (err) {
- throw err;
- }
- stream.emit('metadata', response.metadata);
- });
- var status_batch = {};
- status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
- call.startBatch(status_batch, function(err, response) {
- if (err) {
- throw err;
+ this.updateMetadata(metadata, function(error, metadata) {
+ if (error) {
+ call.cancel();
+ stream.emit('error', error);
+ return;
}
- stream.emit('status', response.status);
+ var start_batch = {};
+ start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
+ start_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
+ call.startBatch(start_batch, function(err, response) {
+ if (err) {
+ throw err;
+ }
+ stream.emit('metadata', response.metadata);
+ });
+ var status_batch = {};
+ status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
+ call.startBatch(status_batch, function(err, response) {
+ if (err) {
+ throw err;
+ }
+ stream.emit('status', response.status);
+ });
});
return stream;
}
@@ -438,8 +466,17 @@ function makeClientConstructor(service) {
* @constructor
* @param {string} address The address of the server to connect to
* @param {Object} options Options to pass to the underlying channel
+ * @param {function(Object, function)=} updateMetadata function to update the
+ * metadata for each request
*/
- function Client(address, options) {
+ function Client(address, options, updateMetadata) {
+ if (updateMetadata) {
+ this.updateMetadata = updateMetadata;
+ } else {
+ this.updateMetadata = function(metadata, callback) {
+ callback(null, metadata);
+ };
+ }
this.channel = new grpc.Channel(address, options);
}
@@ -458,11 +495,13 @@ function makeClientConstructor(service) {
method_type = 'unary';
}
}
- Client.prototype[decapitalize(method.name)] =
- requester_makers[method_type](
- prefix + capitalize(method.name),
- common.serializeCls(method.resolvedRequestType.build()),
- common.deserializeCls(method.resolvedResponseType.build()));
+ var serialize = common.serializeCls(method.resolvedRequestType.build());
+ var deserialize = common.deserializeCls(
+ method.resolvedResponseType.build());
+ Client.prototype[decapitalize(method.name)] = requester_makers[method_type](
+ prefix + capitalize(method.name), serialize, deserialize);
+ Client.prototype[decapitalize(method.name)].serialize = serialize;
+ Client.prototype[decapitalize(method.name)].deserialize = deserialize;
});
Client.service = service;
diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js
index 16def1fa70..d1bdd1660f 100644
--- a/src/node/test/interop_sanity_test.js
+++ b/src/node/test/interop_sanity_test.js
@@ -53,30 +53,35 @@ describe('Interop tests', function() {
});
// This depends on not using a binary stream
it('should pass empty_unary', function(done) {
- interop_client.runTest(port, name_override, 'empty_unary', true, done);
+ interop_client.runTest(port, name_override, 'empty_unary', true, true,
+ done);
});
// This fails due to an unknown bug
it('should pass large_unary', function(done) {
- interop_client.runTest(port, name_override, 'large_unary', true, done);
+ interop_client.runTest(port, name_override, 'large_unary', true, true,
+ done);
});
it('should pass client_streaming', function(done) {
- interop_client.runTest(port, name_override, 'client_streaming', true, done);
+ interop_client.runTest(port, name_override, 'client_streaming', true, true,
+ done);
});
it('should pass server_streaming', function(done) {
- interop_client.runTest(port, name_override, 'server_streaming', true, done);
+ interop_client.runTest(port, name_override, 'server_streaming', true, true,
+ done);
});
it('should pass ping_pong', function(done) {
- interop_client.runTest(port, name_override, 'ping_pong', true, done);
+ interop_client.runTest(port, name_override, 'ping_pong', true, true, done);
});
it('should pass empty_stream', function(done) {
- interop_client.runTest(port, name_override, 'empty_stream', true, done);
+ interop_client.runTest(port, name_override, 'empty_stream', true, true,
+ done);
});
it('should pass cancel_after_begin', function(done) {
interop_client.runTest(port, name_override, 'cancel_after_begin', true,
- done);
+ true, done);
});
it('should pass cancel_after_first_response', function(done) {
interop_client.runTest(port, name_override, 'cancel_after_first_response',
- true, done);
+ true, true, done);
});
});
diff --git a/src/objective-c/.gitignore b/src/objective-c/.gitignore
new file mode 100644
index 0000000000..ec839c09eb
--- /dev/null
+++ b/src/objective-c/.gitignore
@@ -0,0 +1,18 @@
+# Xcode
+#
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+*.xccheckout
+*.moved-aside
+DerivedData
+*.hmap
+*.ipa
+*.xcuserstate
diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h
new file mode 100644
index 0000000000..10437cb8bc
--- /dev/null
+++ b/src/objective-c/GRPCClient/GRPCCall.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+#import <RxLibrary/GRXWriter.h>
+
+@class GRPCMethodName;
+
+@class GRPCCall;
+
+// The gRPC protocol is an RPC protocol on top of HTTP2.
+//
+// While the most common type of RPC receives only one request message and
+// returns only one response message, the protocol also supports RPCs that
+// return multiple individual messages in a streaming fashion, RPCs that
+// accept a stream of request messages, or RPCs with both streaming requests
+// and responses.
+//
+// Conceptually, each gRPC call consists of a bidirectional stream of binary
+// messages, with RPCs of the "non-streaming type" sending only one message in
+// the corresponding direction (the protocol doesn't make any distinction).
+//
+// Each RPC uses a different HTTP2 stream, and thus multiple simultaneous RPCs
+// can be multiplexed transparently on the same TCP connection.
+@interface GRPCCall : NSObject<GRXWriter>
+
+// These HTTP2 headers will be passed to the server as part of this call. Each
+// HTTP2 header is a name-value pair with string names and either string or binary values.
+// The passed dictionary has to use NSString keys, corresponding to the header names. The
+// value associated to each can be a NSString object or a NSData object. E.g.:
+//
+// call.requestMetadata = @{
+// @"Authorization": @"Bearer ...",
+// @"SomeBinaryHeader": someData
+// };
+//
+// After the call is started, modifying this won't have any effect.
+@property(nonatomic, readwrite) NSMutableDictionary *requestMetadata;
+
+// This isn't populated until the first event is delivered to the handler.
+@property(atomic, readonly) NSDictionary *responseMetadata;
+
+// The request writer has to write NSData objects into the provided Writeable. The server will
+// receive each of those separately and in order.
+// A gRPC call might not complete until the request writer finishes. On the other hand, the
+// request finishing doesn't necessarily make the call to finish, as the server might continue
+// sending messages to the response side of the call indefinitely (depending on the semantics of
+// the specific remote method called).
+// To finish a call right away, invoke cancel.
+- (instancetype)initWithHost:(NSString *)host
+ method:(GRPCMethodName *)method
+ requestsWriter:(id<GRXWriter>)requestsWriter NS_DESIGNATED_INITIALIZER;
+
+// Finishes the request side of this call, notifies the server that the RPC
+// should be cancelled, and finishes the response side of the call with an error
+// of code CANCELED.
+- (void)cancel;
+
+// TODO(jcanizales): Let specify a deadline. As a category of GRXWriter?
+@end
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
new file mode 100644
index 0000000000..46a1e232e3
--- /dev/null
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -0,0 +1,406 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRPCCall.h"
+
+#include <grpc.h>
+#include <support/time.h>
+
+#import "GRPCMethodName.h"
+#import "private/GRPCChannel.h"
+#import "private/GRPCCompletionQueue.h"
+#import "private/GRPCDelegateWrapper.h"
+#import "private/GRPCMethodName+HTTP2Encoding.h"
+#import "private/NSData+GRPC.h"
+#import "private/NSDictionary+GRPC.h"
+#import "private/NSError+GRPC.h"
+
+// A grpc_call_error represents a precondition failure when invoking the
+// grpc_call_* functions. If one ever happens, it's a bug in this library.
+//
+// TODO(jcanizales): Can an application shut down gracefully when a thread other
+// than the main one throws an exception?
+static void AssertNoErrorInCall(grpc_call_error error) {
+ if (error != GRPC_CALL_OK) {
+ @throw [NSException exceptionWithName:NSInternalInconsistencyException
+ reason:@"Precondition of grpc_call_* not met."
+ userInfo:nil];
+ }
+}
+
+@interface GRPCCall () <GRXWriteable>
+// Makes it readwrite.
+@property(atomic, strong) NSDictionary *responseMetadata;
+@end
+
+// The following methods of a C gRPC call object aren't reentrant, and thus
+// calls to them must be serialized:
+// - add_metadata
+// - invoke
+// - start_write
+// - writes_done
+// - start_read
+// - destroy
+// The first four are called as part of responding to client commands, but
+// start_read we want to call as soon as we're notified that the RPC was
+// successfully established (which happens concurrently in the network queue).
+// Serialization is achieved by using a private serial queue to operate the
+// call object.
+// Because add_metadata and invoke are called and return successfully before
+// any of the other methods is called, they don't need to use the queue.
+//
+// Furthermore, start_write and writes_done can only be called after the
+// WRITE_ACCEPTED event for any previous write is received. This is achieved by
+// pausing the requests writer immediately every time it writes a value, and
+// resuming it again when WRITE_ACCEPTED is received.
+//
+// Similarly, start_read can only be called after the READ event for any
+// previous read is received. This is easier to enforce, as we're writing the
+// received messages into the writeable: start_read is enqueued once upon receiving
+// the CLIENT_METADATA_READ event, and then once after receiving each READ
+// event.
+@implementation GRPCCall {
+ dispatch_queue_t _callQueue;
+
+ grpc_call *_gRPCCall;
+ dispatch_once_t _callAlreadyInvoked;
+
+ GRPCChannel *_channel;
+ GRPCCompletionQueue *_completionQueue;
+
+ // The C gRPC library has less guarantees on the ordering of events than we
+ // do. Particularly, in the face of errors, there's no ordering guarantee at
+ // all. This wrapper over our actual writeable ensures thread-safety and
+ // correct ordering.
+ GRPCDelegateWrapper *_responseWriteable;
+ id<GRXWriter> _requestWriter;
+}
+
+@synthesize state = _state;
+
+- (instancetype)init {
+ return [self initWithHost:nil method:nil requestsWriter:nil];
+}
+
+// Designated initializer
+- (instancetype)initWithHost:(NSString *)host
+ method:(GRPCMethodName *)method
+ requestsWriter:(id<GRXWriter>)requestWriter {
+ if (!host || !method) {
+ [NSException raise:NSInvalidArgumentException format:@"Neither host nor method can be nil."];
+ }
+ // TODO(jcanizales): Throw if the requestWriter was already started.
+ if ((self = [super init])) {
+ static dispatch_once_t initialization;
+ dispatch_once(&initialization, ^{
+ grpc_init();
+ });
+
+ _completionQueue = [GRPCCompletionQueue completionQueue];
+
+ _channel = [GRPCChannel channelToHost:host];
+ _gRPCCall = grpc_channel_create_call_old(_channel.unmanagedChannel,
+ method.HTTP2Path.UTF8String,
+ host.UTF8String,
+ gpr_inf_future);
+
+ // Serial queue to invoke the non-reentrant methods of the grpc_call object.
+ _callQueue = dispatch_queue_create("org.grpc.call", NULL);
+
+ _requestWriter = requestWriter;
+ }
+ return self;
+}
+
+#pragma mark Finish
+
+- (void)finishWithError:(NSError *)errorOrNil {
+ _requestWriter.state = GRXWriterStateFinished;
+ _requestWriter = nil;
+ if (errorOrNil) {
+ [_responseWriteable cancelWithError:errorOrNil];
+ } else {
+ [_responseWriteable enqueueSuccessfulCompletion];
+ }
+}
+
+- (void)cancelCall {
+ // Can be called from any thread, any number of times.
+ AssertNoErrorInCall(grpc_call_cancel(_gRPCCall));
+}
+
+- (void)cancel {
+ [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
+ code:GRPCErrorCodeCancelled
+ userInfo:nil]];
+ [self cancelCall];
+}
+
+- (void)dealloc {
+ grpc_call *gRPCCall = _gRPCCall;
+ dispatch_async(_callQueue, ^{
+ grpc_call_destroy(gRPCCall);
+ });
+}
+
+#pragma mark Read messages
+
+// Only called from the call queue.
+// The handler will be called from the network queue.
+- (void)startReadWithHandler:(GRPCEventHandler)handler {
+ AssertNoErrorInCall(grpc_call_start_read_old(_gRPCCall, (__bridge_retained void *)handler));
+}
+
+// Called initially from the network queue once response headers are received,
+// then "recursively" from the responseWriteable queue after each response from the
+// server has been written.
+// If the call is currently paused, this is a noop. Restarting the call will invoke this
+// method.
+// TODO(jcanizales): Rename to readResponseIfNotPaused.
+- (void)startNextRead {
+ if (self.state == GRXWriterStatePaused) {
+ return;
+ }
+ __weak GRPCCall *weakSelf = self;
+ __weak GRPCDelegateWrapper *weakWriteable = _responseWriteable;
+
+ dispatch_async(_callQueue, ^{
+ [weakSelf startReadWithHandler:^(grpc_event *event) {
+ if (!event->data.read) {
+ // No more responses from the server.
+ return;
+ }
+ NSData *data = [NSData grpc_dataWithByteBuffer:event->data.read];
+ if (!data) {
+ // The app doesn't have enough memory to hold the server response. We
+ // don't want to throw, because the app shouldn't crash for a behavior
+ // that's on the hands of any server to have. Instead we finish and ask
+ // the server to cancel.
+ //
+ // TODO(jcanizales): No canonical code is appropriate for this situation
+ // (because it's just a client problem). Use another domain and an
+ // appropriately-documented code.
+ [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
+ code:GRPCErrorCodeInternal
+ userInfo:nil]];
+ [weakSelf cancelCall];
+ return;
+ }
+ [weakWriteable enqueueMessage:data completionHandler:^{
+ [weakSelf startNextRead];
+ }];
+ }];
+ });
+}
+
+#pragma mark Send headers
+
+- (void)addHeaderWithName:(NSString *)name binaryValue:(NSData *)value {
+ grpc_metadata metadata;
+ // Safe to discard const qualifiers; we're not going to modify the contents.
+ metadata.key = (char *)name.UTF8String;
+ metadata.value = (char *)value.bytes;
+ metadata.value_length = value.length;
+ grpc_call_add_metadata_old(_gRPCCall, &metadata, 0);
+}
+
+- (void)addHeaderWithName:(NSString *)name ASCIIValue:(NSString *)value {
+ grpc_metadata metadata;
+ // Safe to discard const qualifiers; we're not going to modify the contents.
+ metadata.key = (char *)name.UTF8String;
+ metadata.value = (char *)value.UTF8String;
+ // The trailing \0 isn't encoded in HTTP2.
+ metadata.value_length = value.length;
+ grpc_call_add_metadata_old(_gRPCCall, &metadata, 0);
+}
+
+// TODO(jcanizales): Rename to commitHeaders.
+- (void)sendHeaders:(NSDictionary *)metadata {
+ for (NSString *name in metadata) {
+ id value = metadata[name];
+ if ([value isKindOfClass:[NSData class]]) {
+ [self addHeaderWithName:name binaryValue:value];
+ } else if ([value isKindOfClass:[NSString class]]) {
+ [self addHeaderWithName:name ASCIIValue:value];
+ }
+ }
+}
+
+#pragma mark GRXWriteable implementation
+
+// Only called from the call queue. The error handler will be called from the
+// network queue if the write didn't succeed.
+- (void)writeMessage:(NSData *)message withErrorHandler:(void (^)())errorHandler {
+
+ __weak GRPCCall *weakSelf = self;
+ GRPCEventHandler resumingHandler = ^(grpc_event *event) {
+ if (event->data.write_accepted != GRPC_OP_OK) {
+ errorHandler();
+ }
+ // Resume the request writer (even in the case of error).
+ // TODO(jcanizales): No need to do it in the case of errors anymore?
+ GRPCCall *strongSelf = weakSelf;
+ if (strongSelf) {
+ strongSelf->_requestWriter.state = GRXWriterStateStarted;
+ }
+ };
+
+ grpc_byte_buffer *buffer = message.grpc_byteBuffer;
+ AssertNoErrorInCall(grpc_call_start_write_old(_gRPCCall,
+ buffer,
+ (__bridge_retained void *)resumingHandler,
+ 0));
+ grpc_byte_buffer_destroy(buffer);
+}
+
+- (void)didReceiveValue:(id)value {
+ // TODO(jcanizales): Throw/assert if value isn't NSData.
+
+ // Pause the input and only resume it when the C layer notifies us that writes
+ // can proceed.
+ _requestWriter.state = GRXWriterStatePaused;
+
+ __weak GRPCCall *weakSelf = self;
+ dispatch_async(_callQueue, ^{
+ [weakSelf writeMessage:value withErrorHandler:^{
+ [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
+ code:GRPCErrorCodeInternal
+ userInfo:nil]];
+ }];
+ });
+}
+
+// Only called from the call queue. The error handler will be called from the
+// network queue if the requests stream couldn't be closed successfully.
+- (void)finishRequestWithErrorHandler:(void (^)())errorHandler {
+ GRPCEventHandler handler = ^(grpc_event *event) {
+ if (event->data.finish_accepted != GRPC_OP_OK) {
+ errorHandler();
+ }
+ };
+ AssertNoErrorInCall(grpc_call_writes_done_old(_gRPCCall, (__bridge_retained void *)handler));
+}
+
+- (void)didFinishWithError:(NSError *)errorOrNil {
+ if (errorOrNil) {
+ [self cancel];
+ } else {
+ __weak GRPCCall *weakSelf = self;
+ dispatch_async(_callQueue, ^{
+ [weakSelf finishRequestWithErrorHandler:^{
+ [weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
+ code:GRPCErrorCodeInternal
+ userInfo:nil]];
+ }];
+ });
+ }
+}
+
+#pragma mark Invoke
+
+// Both handlers will eventually be called, from the network queue. Writes can start immediately
+// after this.
+// The first one (metadataHandler), when the response headers are received.
+// The second one (completionHandler), whenever the RPC finishes for any reason.
+- (void)invokeCallWithMetadataHandler:(GRPCEventHandler)metadataHandler
+ completionHandler:(GRPCEventHandler)completionHandler {
+ AssertNoErrorInCall(grpc_call_invoke_old(_gRPCCall,
+ _completionQueue.unmanagedQueue,
+ (__bridge_retained void *)metadataHandler,
+ (__bridge_retained void *)completionHandler,
+ 0));
+}
+
+- (void)invokeCall {
+ __weak GRPCCall *weakSelf = self;
+ [self invokeCallWithMetadataHandler:^(grpc_event *event) {
+ // Response metadata received.
+ // TODO(jcanizales): Name the type of event->data.client_metadata_read
+ // in the C library so one can actually pass the object to a method.
+ grpc_metadata *entries = event->data.client_metadata_read.elements;
+ size_t count = event->data.client_metadata_read.count;
+ GRPCCall *strongSelf = weakSelf;
+ if (strongSelf) {
+ strongSelf.responseMetadata = [NSDictionary grpc_dictionaryFromMetadata:entries
+ count:count];
+ [strongSelf startNextRead];
+ }
+ } completionHandler:^(grpc_event *event) {
+ // TODO(jcanizales): Merge HTTP2 trailers into response metadata.
+ [weakSelf finishWithError:[NSError grpc_errorFromStatus:&event->data.finished]];
+ }];
+ // Now that the RPC has been initiated, request writes can start.
+ [_requestWriter startWithWriteable:self];
+}
+
+#pragma mark GRXWriter implementation
+
+- (void)startWithWriteable:(id<GRXWriteable>)writeable {
+ // The following produces a retain cycle self:_responseWriteable:self, which is only
+ // broken when didFinishWithError: is sent to the wrapped writeable.
+ // Care is taken not to retain self strongly in any of the blocks used in
+ // the implementation of GRPCCall, so that the life of the instance is
+ // determined by this retain cycle.
+ _responseWriteable = [[GRPCDelegateWrapper alloc] initWithWriteable:writeable writer:self];
+ [self sendHeaders:_requestMetadata];
+ [self invokeCall];
+}
+
+- (void)setState:(GRXWriterState)newState {
+ // Manual transitions are only allowed from the started or paused states.
+ if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) {
+ return;
+ }
+
+ switch (newState) {
+ case GRXWriterStateFinished:
+ _state = newState;
+ // Per GRXWriter's contract, setting the state to Finished manually
+ // means one doesn't wish the writeable to be messaged anymore.
+ [_responseWriteable cancelSilently];
+ _responseWriteable = nil;
+ return;
+ case GRXWriterStatePaused:
+ _state = newState;
+ return;
+ case GRXWriterStateStarted:
+ if (_state == GRXWriterStatePaused) {
+ _state = newState;
+ [self startNextRead];
+ }
+ return;
+ case GRXWriterStateNotStarted:
+ return;
+ }
+}
+@end
diff --git a/src/objective-c/GRPCClient/GRPCMethodName.h b/src/objective-c/GRPCClient/GRPCMethodName.h
new file mode 100644
index 0000000000..a62c479788
--- /dev/null
+++ b/src/objective-c/GRPCClient/GRPCMethodName.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+// See the README file for an introduction to this library.
+
+// A fully-qualified gRPC method name. Full qualification is needed because a gRPC endpoint can
+// implement multiple interfaces.
+// TODO(jcanizales): Is this proto-specific, or actual part of gRPC? If the former, move one layer up.
+@interface GRPCMethodName : NSObject
+@property(nonatomic, readonly) NSString *package;
+@property(nonatomic, readonly) NSString *interface;
+@property(nonatomic, readonly) NSString *method;
+- (instancetype)initWithPackage:(NSString *)package
+ interface:(NSString *)interface
+ method:(NSString *)method;
+@end
diff --git a/src/objective-c/GRPCClient/GRPCMethodName.m b/src/objective-c/GRPCClient/GRPCMethodName.m
new file mode 100644
index 0000000000..fbaf24b9f0
--- /dev/null
+++ b/src/objective-c/GRPCClient/GRPCMethodName.m
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRPCMethodName.h"
+
+@implementation GRPCMethodName
+- (instancetype)initWithPackage:(NSString *)package
+ interface:(NSString *)interface
+ method:(NSString *)method {
+ if ((self = [super init])) {
+ _package = [package copy];
+ _interface = [interface copy];
+ _method = [method copy];
+ }
+ return self;
+}
+@end
diff --git a/src/objective-c/GRPCClient/README.md b/src/objective-c/GRPCClient/README.md
new file mode 100644
index 0000000000..9b87f0316c
--- /dev/null
+++ b/src/objective-c/GRPCClient/README.md
@@ -0,0 +1,4 @@
+This is a generic gRPC client for Objective-C on iOS.
+
+If you're trying to get started with the library or with gRPC, you should first
+read GRPCCall.h.
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h
new file mode 100644
index 0000000000..7442f1fae4
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+struct grpc_channel;
+
+// Each separate instance of this class represents at least one TCP
+// connection to the provided host. To create a grpc_call, pass the
+// value of the unmanagedChannel property to grpc_channel_create_call.
+// Release this object when the call is finished.
+@interface GRPCChannel : NSObject
+@property(nonatomic, readonly) struct grpc_channel *unmanagedChannel;
+
+// Convenience constructor to allow for reuse of connections.
++ (instancetype)channelToHost:(NSString *)host;
+
+// Designated initializer
+- (instancetype)initWithHost:(NSString *)host;
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
new file mode 100644
index 0000000000..3e6952cfa3
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRPCChannel.h"
+
+#import <grpc.h>
+
+@implementation GRPCChannel
+
++ (instancetype)channelToHost:(NSString *)host {
+ // TODO(jcanizales): Reuse channels.
+ return [[self alloc] initWithHost:host];
+}
+
+- (instancetype)init {
+ return [self initWithHost:nil];
+}
+
+// Designated initializer
+- (instancetype)initWithHost:(NSString *)host {
+ if (!host) {
+ [NSException raise:NSInvalidArgumentException format:@"Host can't be nil."];
+ }
+ if ((self = [super init])) {
+ _unmanagedChannel = grpc_channel_create(host.UTF8String, NULL);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ // TODO(jcanizales): Be sure to add a test with a server that closes the connection prematurely,
+ // as in the past that made this call to crash.
+ grpc_channel_destroy(_unmanagedChannel);
+}
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
new file mode 100644
index 0000000000..0a8e397443
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+struct grpc_completion_queue;
+struct grpc_event;
+
+typedef void(^GRPCEventHandler)(struct grpc_event *event);
+
+// This class lets one more easily use grpc_completion_queue. To use it, pass
+// the value of the unmanagedQueue property of an instance of this class to
+// grpc_call_start_invoke. Then for every grpc_call_* method that accepts a tag,
+// you can pass a block of type GRPCEventHandler (remembering to cast it using
+// __bridge_retained). The block is guaranteed to eventually be called, by a
+// concurrent queue, and then released. Each such block is passed a pointer to
+// the grpc_event that carried it (in event->tag).
+// Release the GRPCCompletionQueue object only after you are not going to pass
+// any more blocks to the grpc_call that's using it.
+@interface GRPCCompletionQueue : NSObject
+@property(nonatomic, readonly) struct grpc_completion_queue *unmanagedQueue;
+
++ (instancetype)completionQueue;
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
new file mode 100644
index 0000000000..c81e9a2a98
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
@@ -0,0 +1,106 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRPCCompletionQueue.h"
+
+#import <grpc.h>
+
+@implementation GRPCCompletionQueue
+
++ (instancetype)completionQueue {
+ // TODO(jcanizales): Reuse completion queues to consume only one thread,
+ // instead of one per call.
+ return [[self alloc] init];
+}
+
+- (instancetype)init {
+ if ((self = [super init])) {
+ _unmanagedQueue = grpc_completion_queue_create();
+
+ // This is for the following block to capture the pointer by value (instead
+ // of retaining self and doing self->_unmanagedQueue). This is essential
+ // because the block doesn't end until after grpc_completion_queue_shutdown
+ // is called, and we only want that to happen after nobody's using the queue
+ // anymore (i.e. on self dealloc). So the block would never end if it
+ // retained self.
+ grpc_completion_queue *unmanagedQueue = _unmanagedQueue;
+
+ // Start a loop on a concurrent queue to read events from the completion
+ // queue and dispatch each.
+ static dispatch_once_t initialization;
+ static dispatch_queue_t gDefaultConcurrentQueue;
+ dispatch_once(&initialization, ^{
+ gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+ });
+ dispatch_async(gDefaultConcurrentQueue, ^{
+ while (YES) {
+ // The following call blocks until an event is available.
+ grpc_event *event = grpc_completion_queue_next(unmanagedQueue, gpr_inf_future);
+ switch (event->type) {
+ case GRPC_WRITE_ACCEPTED:
+ case GRPC_FINISH_ACCEPTED:
+ case GRPC_CLIENT_METADATA_READ:
+ case GRPC_READ:
+ case GRPC_FINISHED:
+ if (event->tag) {
+ GRPCEventHandler handler = (__bridge_transfer GRPCEventHandler) event->tag;
+ handler(event);
+ }
+ grpc_event_finish(event);
+ continue;
+ case GRPC_QUEUE_SHUTDOWN:
+ grpc_completion_queue_destroy(unmanagedQueue);
+ grpc_event_finish(event);
+ return;
+ case GRPC_SERVER_RPC_NEW:
+ NSAssert(NO, @"C gRPC library produced a server-only event.");
+ continue;
+ }
+ // This means the C gRPC library produced an event that wasn't known
+ // when this library was written. To preserve evolvability, ignore the
+ // unknown event on release builds.
+ NSAssert(NO, @"C gRPC library produced an unknown event.");
+ };
+ });
+ }
+ return self;
+}
+
+- (void)dealloc {
+ // This makes the completion queue produce a GRPC_QUEUE_SHUTDOWN event *after*
+ // all other pending events are flushed. What this means is all the blocks
+ // passed to the gRPC C library as void* are eventually called, even if some
+ // are called after self is dealloc'd.
+ grpc_completion_queue_shutdown(_unmanagedQueue);
+}
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h
new file mode 100644
index 0000000000..b8a73b12df
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+@protocol GRXWriteable;
+@protocol GRXWriter;
+
+// This is a thread-safe wrapper over a GRXWriteable instance. It lets one
+// enqueue calls to a GRXWriteable instance for the main thread, guaranteeing
+// that didFinishWithError: is the last message sent to it (no matter what
+// messages are sent to the wrapper, in what order, nor from which thread). It
+// also guarantees that, if cancelWithError: is called from the main thread
+// (e.g. by the app cancelling the writes), no further messages are sent to the
+// writeable except didFinishWithError:.
+//
+// TODO(jcanizales): Let the user specify another queue for the writeable
+// callbacks.
+// TODO(jcanizales): Rename to GRXWriteableWrapper and move to the Rx library.
+@interface GRPCDelegateWrapper : NSObject
+
+// The GRXWriteable passed is the wrapped writeable.
+// Both the GRXWriter instance and the GRXWriteable instance are retained until
+// didFinishWithError: is sent to the writeable, and released after that.
+// This is used to create a retain cycle that keeps both objects alive until the
+// writing is explicitly finished.
+- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(id<GRXWriter>)writer
+ NS_DESIGNATED_INITIALIZER;
+
+// Enqueues didReceiveValue: to be sent to the writeable in the main thread.
+// The passed handler is invoked from the main thread after didReceiveValue:
+// returns.
+- (void)enqueueMessage:(NSData *)message completionHandler:(void (^)())handler;
+
+// Enqueues didFinishWithError:nil to be sent to the writeable in the main
+// thread. After that message is sent to the writeable, all other methods of
+// this object are effectively noops.
+- (void)enqueueSuccessfulCompletion;
+
+// If the writeable has not yet received a didFinishWithError: message, this
+// will enqueue one to be sent to it in the main thread, and cancel all other
+// pending messages to the writeable enqueued by this object (both past and
+// future).
+// The error argument cannot be nil.
+- (void)cancelWithError:(NSError *)error;
+
+// Cancels all pending messages to the writeable enqueued by this object (both
+// past and future). Because the writeable won't receive didFinishWithError:,
+// this also releases the writeable and the writer.
+- (void)cancelSilently;
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m
new file mode 100644
index 0000000000..73a2f51f1b
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m
@@ -0,0 +1,120 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRPCDelegateWrapper.h"
+
+#import <net/grpc/objc/RxLibrary/GRXWriteable.h>
+
+@interface GRPCDelegateWrapper ()
+// These are atomic so that cancellation can nillify them from any thread.
+@property(atomic, strong) id<GRXWriteable> writeable;
+@property(atomic, strong) id<GRXWriter> writer;
+@end
+
+@implementation GRPCDelegateWrapper {
+ dispatch_queue_t _writeableQueue;
+ // This ensures that didFinishWithError: is only sent once to the writeable.
+ dispatch_once_t _alreadyFinished;
+}
+
+- (instancetype)init {
+ return [self initWithWriteable:nil writer:nil];
+}
+
+// Designated initializer
+- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(id<GRXWriter>)writer {
+ if (self = [super init]) {
+ _writeableQueue = dispatch_get_main_queue();
+ _writeable = writeable;
+ _writer = writer;
+ }
+ return self;
+}
+
+- (void)enqueueMessage:(NSData *)message completionHandler:(void (^)())handler {
+ dispatch_async(_writeableQueue, ^{
+ // We're racing a possible cancellation performed by another thread. To turn
+ // all already-enqueued messages into noops, cancellation nillifies the
+ // writeable property. If we get it before it's nil, we won
+ // the race.
+ id<GRXWriteable> writeable = self.writeable;
+ if (writeable) {
+ [writeable didReceiveValue:message];
+ handler();
+ }
+ });
+}
+
+- (void)enqueueSuccessfulCompletion {
+ dispatch_async(_writeableQueue, ^{
+ dispatch_once(&_alreadyFinished, ^{
+ // Cancellation is now impossible. None of the other three blocks can run
+ // concurrently with this one.
+ [self.writeable didFinishWithError:nil];
+ // Break the retain cycle with writer, and skip any possible message to the
+ // wrapped writeable enqueued after this one.
+ self.writeable = nil;
+ self.writer = nil;
+ });
+ });
+}
+
+- (void)cancelWithError:(NSError *)error {
+ NSAssert(error, @"For a successful completion, use enqueueSuccessfulCompletion.");
+ dispatch_once(&_alreadyFinished, ^{
+ // Skip any of the still-enqueued messages to the wrapped writeable. We use
+ // the atomic setter to nillify writer and writeable because we might be
+ // running concurrently with the blocks in _writeableQueue, and assignment
+ // with ARC isn't atomic.
+ id<GRXWriteable> writeable = self.writeable;
+ self.writeable = nil;
+
+ dispatch_async(_writeableQueue, ^{
+ [writeable didFinishWithError:error];
+ // Break the retain cycle with writer.
+ self.writer = nil;
+ });
+ });
+}
+
+- (void)cancelSilently {
+ dispatch_once(&_alreadyFinished, ^{
+ // Skip any of the still-enqueued messages to the wrapped writeable. We use
+ // the atomic setter to nillify writer and writeable because we might be
+ // running concurrently with the blocks in _writeableQueue, and assignment
+ // with ARC isn't atomic.
+ self.writeable = nil;
+ self.writer = nil;
+ });
+}
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h b/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h
new file mode 100644
index 0000000000..05e35bb1a3
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "GRPCMethodName.h"
+
+@interface GRPCMethodName (HTTP2Encoding)
+- (NSString *)HTTP2Path;
+@end
diff --git a/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m b/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m
new file mode 100644
index 0000000000..3fb9af25ec
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/GRPCMethodName+HTTP2Encoding.m
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRPCMethodName+HTTP2Encoding.h"
+
+@implementation GRPCMethodName (HTTP2Encoding)
+- (NSString *)HTTP2Path {
+ if (self.package) {
+ return [NSString stringWithFormat:@"/%@.%@/%@", self.package, self.interface, self.method];
+ } else {
+ return [NSString stringWithFormat:@"/%@/%@", self.interface, self.method];
+ }
+}
+@end
diff --git a/src/objective-c/GRPCClient/private/NSData+GRPC.h b/src/objective-c/GRPCClient/private/NSData+GRPC.h
new file mode 100644
index 0000000000..936c2a0e8a
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/NSData+GRPC.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+struct grpc_byte_buffer;
+
+@interface NSData (GRPC)
++ (instancetype)grpc_dataWithByteBuffer:(struct grpc_byte_buffer *)buffer;
+- (struct grpc_byte_buffer *)grpc_byteBuffer;
+@end
diff --git a/src/objective-c/GRPCClient/private/NSData+GRPC.m b/src/objective-c/GRPCClient/private/NSData+GRPC.m
new file mode 100644
index 0000000000..b5f952722c
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/NSData+GRPC.m
@@ -0,0 +1,86 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "NSData+GRPC.h"
+
+#include <byte_buffer.h>
+#include <string.h>
+
+// TODO(jcanizales): Move these two incantations to the C library.
+
+static void CopyByteBufferToCharArray(grpc_byte_buffer *buffer, char *array) {
+ size_t offset = 0;
+ grpc_byte_buffer_reader *reader = grpc_byte_buffer_reader_create(buffer);
+ gpr_slice next;
+ while (grpc_byte_buffer_reader_next(reader, &next) != 0){
+ memcpy(array + offset, GPR_SLICE_START_PTR(next), (size_t) GPR_SLICE_LENGTH(next));
+ offset += GPR_SLICE_LENGTH(next);
+ gpr_slice_unref(next);
+ }
+ grpc_byte_buffer_reader_destroy(reader);
+}
+
+static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, size_t length) {
+ gpr_slice slice = gpr_slice_from_copied_buffer(array, length);
+ grpc_byte_buffer *buffer = grpc_byte_buffer_create(&slice, 1);
+ gpr_slice_unref(slice);
+ return buffer;
+}
+
+@implementation NSData (GRPC)
++ (instancetype)grpc_dataWithByteBuffer:(grpc_byte_buffer *)buffer {
+ NSUInteger length = grpc_byte_buffer_length(buffer);
+ char *array = malloc(length * sizeof(*array));
+ if (!array) {
+ // TODO(jcanizales): grpc_byte_buffer is reference-counted, so we can
+ // prevent this memory problem by implementing a subclass of NSData
+ // that wraps the grpc_byte_buffer. Then enumerateByteRangesUsingBlock:
+ // can be implemented using a grpc_byte_buffer_reader.
+ return nil;
+ }
+ CopyByteBufferToCharArray(buffer, array);
+ return [self dataWithBytesNoCopy:array length:length freeWhenDone:YES];
+}
+
+- (grpc_byte_buffer *)grpc_byteBuffer {
+ // Some implementations of NSData, as well as grpc_byte_buffer, support O(1)
+ // appending of byte arrays by not using internally a single contiguous memory
+ // block for representation.
+ // The following implementation is thus not optimal, sometimes requiring two
+ // copies (one by self.bytes and another by gpr_slice_from_copied_buffer).
+ // If it turns out to be an issue, we can use enumerateByteRangesUsingblock:
+ // to create an array of gpr_slice objects to pass to grpc_byte_buffer_create.
+ // That would make it do exactly one copy, always.
+ return CopyCharArrayToNewByteBuffer((const char *)self.bytes, (size_t)self.length);
+}
+@end
diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.h b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.h
new file mode 100644
index 0000000000..bf0233fd46
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+struct grpc_metadata;
+
+@interface NSDictionary (GRPC)
++ (instancetype)grpc_dictionaryFromMetadata:(struct grpc_metadata *)entries count:(size_t)count;
+@end
diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
new file mode 100644
index 0000000000..345ff3e1e6
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "NSDictionary+GRPC.h"
+
+#include <grpc.h>
+
+@implementation NSDictionary (GRPC)
++ (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count {
+ NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count];
+ for (grpc_metadata *entry = entries; entry < entries + count; entry++) {
+ // TODO(jcanizales): Verify in a C library test that it's converting header names to lower case automatically.
+ NSString *name = [NSString stringWithUTF8String:entry->key];
+ if (!name) {
+ continue;
+ }
+ if (!metadata[name]) {
+ metadata[name] = [NSMutableArray array];
+ }
+ // TODO(jcanizales): Should we use a non-copy constructor?
+ [metadata[name] addObject:[NSData dataWithBytes:entry->value
+ length:entry->value_length]];
+ }
+ return metadata;
+}
+@end
diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.h b/src/objective-c/GRPCClient/private/NSError+GRPC.h
new file mode 100644
index 0000000000..b7439fa067
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/NSError+GRPC.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+// TODO(jcanizales): Make the domain string public.
+extern NSString *const kGRPCErrorDomain;
+
+// TODO(jcanizales): Make this public and document each code.
+typedef NS_ENUM(NSInteger, GRPCErrorCode) {
+ GRPCErrorCodeCancelled = 1,
+ GRPCErrorCodeUnknown = 2,
+ GRPCErrorCodeInvalidArgument = 3,
+ GRPCErrorCodeDeadlineExceeded = 4,
+ GRPCErrorCodeNotFound = 5,
+ GRPCErrorCodeAlreadyExists = 6,
+ GRPCErrorCodePermissionDenied = 7,
+ GRPCErrorCodeUnauthenticated = 16,
+ GRPCErrorCodeResourceExhausted = 8,
+ GRPCErrorCodeFailedPrecondition = 9,
+ GRPCErrorCodeAborted = 10,
+ GRPCErrorCodeOutOfRange = 11,
+ GRPCErrorCodeUnimplemented = 12,
+ GRPCErrorCodeInternal = 13,
+ GRPCErrorCodeUnavailable = 14,
+ GRPCErrorCodeDataLoss = 15
+};
+
+// TODO(jcanizales): This is conflating trailing metadata with Status details. Fix it once there's
+// a decision on how to codify Status.
+#include <grpc/status.h>
+struct grpc_metadata;
+struct grpc_status {
+ grpc_status_code status;
+ const char *details;
+ size_t metadata_count;
+ struct grpc_metadata *metadata_elements;
+};
+
+@interface NSError (GRPC)
+// Returns nil if the status is OK. Otherwise, a NSError whose code is one of
+// GRPCErrorCode and whose domain is kGRPCErrorDomain.
++ (instancetype)grpc_errorFromStatus:(struct grpc_status *)status;
+@end
diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.m b/src/objective-c/GRPCClient/private/NSError+GRPC.m
new file mode 100644
index 0000000000..4fc1249efc
--- /dev/null
+++ b/src/objective-c/GRPCClient/private/NSError+GRPC.m
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "NSError+GRPC.h"
+
+#include <grpc.h>
+
+NSString *const kGRPCErrorDomain = @"org.grpc";
+
+@implementation NSError (GRPC)
++ (instancetype)grpc_errorFromStatus:(struct grpc_status *)status {
+ if (status->status == GRPC_STATUS_OK) {
+ return nil;
+ }
+ NSString *message =
+ [NSString stringWithFormat:@"Code=%i Message='%s'", status->status, status->details];
+ return [NSError errorWithDomain:kGRPCErrorDomain
+ code:status->status
+ userInfo:@{NSLocalizedDescriptionKey: message}];
+}
+@end
diff --git a/src/objective-c/README.md b/src/objective-c/README.md
new file mode 100644
index 0000000000..05e9f2b4dc
--- /dev/null
+++ b/src/objective-c/README.md
@@ -0,0 +1,3 @@
+gRPC implementation for Objective-C on iOS
+
+This is a work in progress.
diff --git a/src/objective-c/RxLibrary/GRXImmediateWriter.h b/src/objective-c/RxLibrary/GRXImmediateWriter.h
new file mode 100644
index 0000000000..74f4dc69f4
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXImmediateWriter.h
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "GRXWriter.h"
+
+// Utility to construct GRXWriter instances from values that are immediately available when
+// required. The returned writers all support pausing and early termination.
+//
+// Unless the writeable callback pauses them or stops them early, these writers will do all their
+// interactions with the writeable before the start method returns.
+@interface GRXImmediateWriter : NSObject<GRXWriter>
+
+// Returns a writer that pulls values from the passed NSEnumerator instance and pushes them to
+// its writeable. The NSEnumerator is released when it finishes.
++ (id<GRXWriter>)writerWithEnumerator:(NSEnumerator *)enumerator;
+
+// Returns a writer that pushes to its writeable the successive values returned by the passed
+// block. When the block first returns nil, it is released.
++ (id<GRXWriter>)writerWithValueSupplier:(id (^)())block;
+
+// Returns a writer that iterates over the values of the passed container and pushes them to
+// its writeable. The container is released when the iteration is over.
+//
+// Note that the usual speed gain of NSFastEnumeration over NSEnumerator results from not having to
+// call one method per element. Because GRXWriteable instances accept values one by one, that speed
+// gain doesn't happen here.
++ (id<GRXWriter>)writerWithContainer:(id<NSFastEnumeration>)container;
+
+// Returns a writer that sends the passed value to its writeable and then finishes (releasing the
+// value).
++ (id<GRXWriter>)writerWithValue:(id)value;
+
+// Returns a writer that, as part of its start method, sends the passed error to the writeable
+// (then releasing the error).
++ (id<GRXWriter>)writerWithError:(NSError *)error;
+
+// Returns a writer that, as part of its start method, finishes immediately without sending any
+// values to its writeable.
++ (id<GRXWriter>)emptyWriter;
+
+@end
diff --git a/src/objective-c/RxLibrary/GRXImmediateWriter.m b/src/objective-c/RxLibrary/GRXImmediateWriter.m
new file mode 100644
index 0000000000..4417ae8f16
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXImmediateWriter.m
@@ -0,0 +1,165 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXImmediateWriter.h"
+
+#import "NSEnumerator+GRXUtil.h"
+
+@implementation GRXImmediateWriter {
+ NSEnumerator *_enumerator;
+ NSError *_errorOrNil;
+ id<GRXWriteable> _writeable;
+}
+
+@synthesize state = _state;
+
+- (instancetype) init {
+ return [self initWithEnumerator:nil error:nil]; // results in an empty writer.
+}
+
+// Designated initializer
+- (instancetype)initWithEnumerator:(NSEnumerator *)enumerator error:(NSError *)errorOrNil {
+ if (((self = [super init]))) {
+ _enumerator = enumerator;
+ _errorOrNil = errorOrNil;
+ _state = GRXWriterStateNotStarted;
+ }
+ return self;
+}
+
+#pragma mark Convenience constructors
+
++ (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator error:(NSError *)errorOrNil {
+ return [[self alloc] initWithEnumerator:enumerator error:errorOrNil];
+}
+
++ (id<GRXWriter>)writerWithEnumerator:(NSEnumerator *)enumerator {
+ return [self writerWithEnumerator:enumerator error:nil];
+}
+
++ (id<GRXWriter>)writerWithValueSupplier:(id (^)())block {
+ return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithValueSupplier:block]];
+}
+
++ (id<GRXWriter>)writerWithContainer:(id<NSFastEnumeration>)container {
+ return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];;
+}
+
++ (id<GRXWriter>)writerWithValue:(id)value {
+ if (value) {
+ return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithSingleValue:value]];
+ } else {
+ return [self emptyWriter];
+ }
+}
+
++ (id<GRXWriter>)writerWithError:(NSError *)error {
+ if (error) {
+ return [self writerWithEnumerator:nil error:error];
+ } else {
+ return [self emptyWriter];
+ }
+}
+
++ (id<GRXWriter>)emptyWriter {
+ static GRXImmediateWriter *emptyWriter;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ emptyWriter = [self writerWithEnumerator:nil error:nil];
+ });
+ return emptyWriter;
+}
+
+#pragma mark Conformance with GRXWriter
+
+// Most of the complexity in this implementation is the result of supporting pause and resumption of
+// the GRXWriter. It's an important feature for instances of GRXWriter that are backed by a
+// container (which may be huge), or by a NSEnumerator (which may even be infinite).
+
+- (void)writeUntilPausedOrStopped {
+ id value;
+ while (value = [_enumerator nextObject]) {
+ [_writeable didReceiveValue:value];
+ // If the writeable has a reference to us, it might change our state to paused or finished.
+ if (_state == GRXWriterStatePaused || _state == GRXWriterStateFinished) {
+ return;
+ }
+ }
+ [self finishWithError:_errorOrNil];
+}
+
+- (void)startWithWriteable:(id<GRXWriteable>)writeable {
+ _state = GRXWriterStateStarted;
+ _writeable = writeable;
+ [self writeUntilPausedOrStopped];
+}
+
+- (void)finishWithError:(NSError *)errorOrNil {
+ _state = GRXWriterStateFinished;
+ _enumerator = nil;
+ _errorOrNil = nil;
+ id<GRXWriteable> writeable = _writeable;
+ _writeable = nil;
+ [writeable didFinishWithError:errorOrNil];
+}
+
+- (void)setState:(GRXWriterState)newState {
+ // Manual transitions are only allowed from the started or paused states.
+ if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) {
+ return;
+ }
+
+ switch (newState) {
+ case GRXWriterStateFinished:
+ _state = newState;
+ _enumerator = nil;
+ _errorOrNil = nil;
+ // Per GRXWriter's contract, setting the state to Finished manually
+ // means one doesn't wish the writeable to be messaged anymore.
+ _writeable = nil;
+ return;
+ case GRXWriterStatePaused:
+ _state = newState;
+ return;
+ case GRXWriterStateStarted:
+ if (_state == GRXWriterStatePaused) {
+ _state = newState;
+ [self writeUntilPausedOrStopped];
+ }
+ return;
+ case GRXWriterStateNotStarted:
+ return;
+ }
+}
+
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriteable.h b/src/objective-c/RxLibrary/GRXWriteable.h
new file mode 100644
index 0000000000..5aa00ba40e
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriteable.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+// A GRXWriteable is an object to which a sequence of values can be sent. The
+// sequence finishes with an optional error.
+@protocol GRXWriteable <NSObject>
+
+// Push the next value of the sequence to the receiving object.
+// TODO(jcanizales): Name it enumerator:(id<GRXEnumerator>) didProduceValue:(id)?
+- (void)didReceiveValue:(id)value;
+
+// Signal that the sequence is completed, or that an error ocurred. After this
+// message is sent to the instance, neither it nor didReceiveValue: may be
+// called again.
+// TODO(jcanizales): enumerator:(id<GRXEnumerator>) didFinishWithError:(NSError*)?
+- (void)didFinishWithError:(NSError *)errorOrNil;
+@end
+
+typedef void (^GRXValueHandler)(id value);
+typedef void (^GRXCompletionHandler)(NSError *errorOrNil);
+
+// Utility to create objects that conform to the GRXWriteable protocol, from
+// blocks that handle each of the two methods of the protocol.
+@interface GRXWriteable : NSObject<GRXWriteable>
+- (instancetype)initWithValueHandler:(GRXValueHandler)valueHandler
+ completionHandler:(GRXCompletionHandler)completionHandler
+ NS_DESIGNATED_INITIALIZER;
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriteable.m b/src/objective-c/RxLibrary/GRXWriteable.m
new file mode 100644
index 0000000000..9567e42b74
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriteable.m
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXWriteable.h"
+
+@implementation GRXWriteable {
+ GRXValueHandler _valueHandler;
+ GRXCompletionHandler _completionHandler;
+}
+
+- (instancetype)init {
+ return [self initWithValueHandler:nil completionHandler:nil];
+}
+
+// Designated initializer
+- (instancetype)initWithValueHandler:(GRXValueHandler)valueHandler
+ completionHandler:(GRXCompletionHandler)completionHandler {
+ if ((self = [super init])) {
+ _valueHandler = valueHandler;
+ _completionHandler = completionHandler;
+ }
+ return self;
+}
+
+- (void)didReceiveValue:(id)value {
+ if (_valueHandler) {
+ _valueHandler(value);
+ }
+}
+
+- (void)didFinishWithError:(NSError *)errorOrNil {
+ if (_completionHandler) {
+ _completionHandler(errorOrNil);
+ }
+}
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriter+Immediate.h b/src/objective-c/RxLibrary/GRXWriter+Immediate.h
new file mode 100644
index 0000000000..101df81e5e
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriter+Immediate.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXWriter.h"
+
+@interface GRXWriter (Immediate)
+
+// Returns a writer that pulls values from the passed NSEnumerator instance and pushes them to
+// its writeable. The NSEnumerator is released when it finishes.
++ (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator;
+
+// Returns a writer that pushes to its writeable the successive values returned by the passed
+// block. When the block first returns nil, it is released.
++ (instancetype)writerWithValueSupplier:(id (^)())block;
+
+// Returns a writer that iterates over the values of the passed container and pushes them to
+// its writeable. The container is released when the iteration is over.
+//
+// Note that the usual speed gain of NSFastEnumeration over NSEnumerator results from not having to
+// call one method per element. Because GRXWriteable instances accept values one by one, that speed
+// gain doesn't happen here.
++ (instancetype)writerWithContainer:(id<NSFastEnumeration>)container;
+
+// Returns a writer that sends the passed value to its writeable and then finishes (releasing the
+// value).
++ (instancetype)writerWithValue:(id)value;
+
+// Returns a writer that, as part of its start method, sends the passed error to the writeable
+// (then releasing the error).
++ (instancetype)writerWithError:(NSError *)error;
+
+// Returns a writer that, as part of its start method, finishes immediately without sending any
+// values to its writeable.
++ (instancetype)emptyWriter;
+
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriter+Immediate.m b/src/objective-c/RxLibrary/GRXWriter+Immediate.m
new file mode 100644
index 0000000000..7dab5e2ba5
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriter+Immediate.m
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXWriter+Immediate.h"
+
+#import "GRXImmediateWriter.h"
+
+@implementation GRXWriter (Immediate)
+
++ (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator {
+ return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithEnumerator:enumerator]];
+}
+
++ (instancetype)writerWithValueSupplier:(id (^)())block {
+ return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithValueSupplier:block]];
+}
+
++ (instancetype)writerWithContainer:(id<NSFastEnumeration>)container {
+ return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithContainer:container]];
+}
+
++ (instancetype)writerWithValue:(id)value {
+ return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithValue:value]];
+}
+
++ (instancetype)writerWithError:(NSError *)error {
+ return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithError:error]];
+}
+
++ (instancetype)emptyWriter {
+ return [[self alloc] initWithWriter:[GRXImmediateWriter emptyWriter]];
+}
+
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriter+Transformations.h b/src/objective-c/RxLibrary/GRXWriter+Transformations.h
new file mode 100644
index 0000000000..cfd644b520
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriter+Transformations.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXWriter.h"
+
+@interface GRXWriter (Transformations)
+
+// Returns a writer that wraps the receiver, and has all the values the receiver would write
+// transformed by the provided mapping function.
+- (GRXWriter *)map:(id (^)(id value))map;
+
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriter+Transformations.m b/src/objective-c/RxLibrary/GRXWriter+Transformations.m
new file mode 100644
index 0000000000..67c54a7e80
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriter+Transformations.m
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXWriter+Transformations.h"
+
+#import "transformations/GRXMappingWriter.h"
+
+@implementation GRXWriter (Transformations)
+
+- (GRXWriter *)map:(id (^)(id))map {
+ if (!map) {
+ return self;
+ }
+ return [[GRXMappingWriter alloc] initWithWriter:self map:map];
+}
+
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriter.h b/src/objective-c/RxLibrary/GRXWriter.h
new file mode 100644
index 0000000000..8bda52fcb9
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriter.h
@@ -0,0 +1,127 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "GRXWriteable.h"
+
+typedef NS_ENUM(NSInteger, GRXWriterState) {
+
+ // The writer has not yet been given a writeable to which it can push its
+ // values. To have an writer transition to the Started state, send it a
+ // startWithWriteable: message.
+ //
+ // An writer's state cannot be manually set to this value.
+ GRXWriterStateNotStarted,
+
+ // The writer might push values to the writeable at any moment.
+ GRXWriterStateStarted,
+
+ // The writer is temporarily paused, and won't send any more values to the
+ // writeable unless its state is set back to Started. The writer might still
+ // transition to the Finished state at any moment, and is allowed to send
+ // didFinishWithError: to its writeable.
+ //
+ // Not all implementations of writer have to support pausing, and thus
+ // trying to set an writer's state to this value might have no effect.
+ GRXWriterStatePaused,
+
+ // The writer has released its writeable and won't interact with it anymore.
+ //
+ // One seldomly wants to set an writer's state to this value, as its
+ // writeable isn't notified with a didFinishWithError: message. Instead, sending
+ // finishWithError: to the writer will make it notify the writeable and then
+ // transition to this state.
+ GRXWriterStateFinished
+};
+
+// An object that conforms to this protocol can produce, on demand, a sequence
+// of values. The sequence may be produced asynchronously, and it may consist of
+// any number of elements, including none or an infinite number.
+//
+// GRXWriter is the active dual of NSEnumerator. The difference between them
+// is thus whether the object plays an active or passive role during usage: A
+// user of NSEnumerator pulls values off it, and passes the values to a writeable.
+// A user of GRXWriter, though, just gives it a writeable, and the
+// GRXWriter instance pushes values to the writeable. This makes this protocol
+// suitable to represent a sequence of future values, as well as collections
+// with internal iteration.
+//
+// An instance of GRXWriter can start producing values after a writeable is
+// passed to it. It can also be commanded to finish the sequence immediately
+// (with an optional error). Finally, it can be asked to pause, but the
+// conforming instance is not required to oblige.
+//
+// Unless otherwise indicated by a conforming class, no messages should be sent
+// concurrently to a GRXWriter. I.e., conforming classes aren't required to
+// be thread-safe.
+@protocol GRXWriter <NSObject>
+
+// This property can be used to query the current state of the writer, which
+// determines how it might currently use its writeable. Some state transitions can
+// be triggered by setting this property to the corresponding value, and that's
+// useful for advanced use cases like pausing an writer. For more details,
+// see the documentation of the enum.
+@property(nonatomic) GRXWriterState state;
+
+// Start sending messages to the writeable. Messages may be sent before the method
+// returns, or they may be sent later in the future. See GRXWriteable.h for the
+// different messages a writeable can receive.
+//
+// If this writer draws its values from an external source (e.g. from the
+// filesystem or from a server), calling this method will commonly trigger side
+// effects (like network connections).
+//
+// This method might only be called on writers in the NotStarted state.
+- (void)startWithWriteable:(id<GRXWriteable>)writeable;
+
+// Send didFinishWithError:errorOrNil immediately to the writeable, and don't send
+// any more messages to it.
+//
+// This method might only be called on writers in the Started or Paused
+// state.
+//
+// TODO(jcanizales): Consider adding some guarantee about the immediacy of that
+// stopping. I know I've relied on it in part of the code that uses this, but
+// can't remember the details in the presence of concurrency.
+- (void)finishWithError:(NSError *)errorOrNil;
+@end
+
+// A "proxy" class that simply forwards values, completion, and errors from its
+// input writer to its writeable.
+// It is useful as a superclass for pipes that act as a transformation of their
+// input writer, and for classes that represent objects with input and
+// output sequences of values, like an RPC.
+@interface GRXWriter : NSObject<GRXWriter>
+- (instancetype)initWithWriter:(id<GRXWriter>)writer NS_DESIGNATED_INITIALIZER;
+@end
diff --git a/src/objective-c/RxLibrary/GRXWriter.m b/src/objective-c/RxLibrary/GRXWriter.m
new file mode 100644
index 0000000000..7d6c2acd36
--- /dev/null
+++ b/src/objective-c/RxLibrary/GRXWriter.m
@@ -0,0 +1,112 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXWriter.h"
+
+@interface GRXWriter () <GRXWriteable>
+@end
+
+@implementation GRXWriter {
+ id<GRXWriter> _writer;
+ id<GRXWriteable> _writeable;
+}
+
+- (instancetype)init {
+ return [self initWithWriter:nil];
+}
+
+// Designated initializer
+- (instancetype)initWithWriter:(id<GRXWriter>)writer {
+ if (!writer) {
+ [NSException raise:NSInvalidArgumentException format:@"writer can't be nil."];
+ }
+ if ((self = [super init])) {
+ _writer = writer;
+ }
+ return self;
+}
+
+// This is used to send a completion or an error to the writeable. It nillifies
+// our reference to it in order to guarantee no more messages are sent to it,
+// and to release it.
+- (void)finishOutputWithError:(NSError *)errorOrNil {
+ id<GRXWriteable> writeable = _writeable;
+ _writeable = nil;
+ [writeable didFinishWithError:errorOrNil];
+}
+
+// This is used to stop the input writer. It nillifies our reference to it
+// to release it.
+- (void)finishInput {
+ id<GRXWriter> writer = _writer;
+ _writer = nil;
+ writer.state = GRXWriterStateFinished;
+}
+
+#pragma mark GRXWriteable implementation
+
+- (void)didReceiveValue:(id)value {
+ [_writeable didReceiveValue:value];
+}
+
+- (void)didFinishWithError:(NSError *)errorOrNil {
+ _writer = nil;
+ [self finishOutputWithError:errorOrNil];
+}
+
+#pragma mark GRXWriter implementation
+
+- (GRXWriterState)state {
+ return _writer ? _writer.state : GRXWriterStateFinished;
+}
+
+- (void)setState:(GRXWriterState)state {
+ if (state == GRXWriterStateFinished) {
+ _writeable = nil;
+ [self finishInput];
+ } else {
+ _writer.state = state;
+ }
+}
+
+- (void)startWithWriteable:(id<GRXWriteable>)writeable {
+ _writeable = writeable;
+ [_writer startWithWriteable:self];
+}
+
+- (void)finishWithError:(NSError *)errorOrNil {
+ [self finishOutputWithError:errorOrNil];
+ [self finishInput];
+}
+
+@end
diff --git a/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.h b/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.h
new file mode 100644
index 0000000000..e3f8bbe9c2
--- /dev/null
+++ b/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSEnumerator (GRXUtil)
+
+// Returns a NSEnumerator instance that iterates through the elements of the passed container that
+// supports fast enumeration. Note that this negates the speed benefits of fast enumeration over
+// NSEnumerator. It's only intended for the rare cases when one needs the latter and only has the
+// former, e.g. for iteration that needs to be paused and resumed later.
++ (NSEnumerator *)grx_enumeratorWithContainer:(id<NSFastEnumeration>)container;
+
+// Returns a NSEnumerator instance that provides a single object before finishing. The value is then
+// released.
++ (NSEnumerator *)grx_enumeratorWithSingleValue:(id)value;
+
+// Returns a NSEnumerator instance that delegates the invocations of nextObject to the passed block.
+// When the block first returns nil, it is released.
++ (NSEnumerator *)grx_enumeratorWithValueSupplier:(id (^)())block;
+@end
diff --git a/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.m b/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.m
new file mode 100644
index 0000000000..807a1cd700
--- /dev/null
+++ b/src/objective-c/RxLibrary/NSEnumerator+GRXUtil.m
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "NSEnumerator+GRXUtil.h"
+
+#import "private/GRXNSBlockEnumerator.h"
+#import "private/GRXNSFastEnumerator.h"
+#import "private/GRXNSScalarEnumerator.h"
+
+@implementation NSEnumerator (GRXUtil)
+
++ (NSEnumerator *)grx_enumeratorWithContainer:(id<NSFastEnumeration>)container {
+ // TODO(jcanizales): Consider checking if container responds to objectEnumerator and return that?
+ return [[GRXNSFastEnumerator alloc] initWithContainer:container];
+}
+
++ (NSEnumerator *)grx_enumeratorWithSingleValue:(id)value {
+ return [[GRXNSScalarEnumerator alloc] initWithValue:value];
+}
+
++ (NSEnumerator *)grx_enumeratorWithValueSupplier:(id (^)())block {
+ return [[GRXNSBlockEnumerator alloc] initWithValueSupplier:block];
+}
+@end
diff --git a/src/objective-c/RxLibrary/README.md b/src/objective-c/RxLibrary/README.md
new file mode 100644
index 0000000000..88e90723b9
--- /dev/null
+++ b/src/objective-c/RxLibrary/README.md
@@ -0,0 +1,8 @@
+This is a generic Reactive Extensions library for Objective-C, created to ease
+the implementation of the gRPC Objective-C runtime.
+
+It has no dependencies on gRPC nor other libraries, and should eventually be
+moved under its own GitHub project.
+
+If you're trying to get started on the library, you might want to first read
+GRXWriter.h and then GRXWriteable.h.
diff --git a/src/objective-c/RxLibrary/RxLibrary.podspec b/src/objective-c/RxLibrary/RxLibrary.podspec
new file mode 100644
index 0000000000..605aedaf10
--- /dev/null
+++ b/src/objective-c/RxLibrary/RxLibrary.podspec
@@ -0,0 +1,13 @@
+Pod::Spec.new do |s|
+ s.name = 'RxLibrary'
+ s.version = '0.0.1'
+ s.summary = 'Reactive Extensions library for iOS'
+ s.author = {
+ 'Jorge Canizales' => 'jcanizales@google.com'
+ }
+ s.source_files = '*.{h,m}', 'transformations/*.{h,m}', 'private/*.{h,m}'
+ s.private_header_files = 'private/*.h'
+ s.platform = :ios
+ s.ios.deployment_target = '6.0'
+ s.requires_arc = true
+end
diff --git a/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.h b/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.h
new file mode 100644
index 0000000000..4253324e95
--- /dev/null
+++ b/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+// Concrete subclass of NSEnumerator that delegates the invocations of nextObject to a block passed
+// on initialization.
+@interface GRXNSBlockEnumerator : NSEnumerator
+// The first time the passed block returns nil, the enumeration will end and the block will be
+// released.
+- (instancetype)initWithValueSupplier:(id (^)())block;
+@end
diff --git a/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.m b/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.m
new file mode 100644
index 0000000000..53b8bb863d
--- /dev/null
+++ b/src/objective-c/RxLibrary/private/GRXNSBlockEnumerator.m
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXNSBlockEnumerator.h"
+
+@implementation GRXNSBlockEnumerator {
+ id (^_block)();
+}
+
+- (instancetype)init {
+ return [self initWithValueSupplier:nil];
+}
+
+- (instancetype)initWithValueSupplier:(id (^)())block {
+ if ((self = [super init])) {
+ _block = block;
+ }
+ return self;
+}
+
+- (id)nextObject {
+ if (!_block) {
+ return nil;
+ }
+ id value = _block();
+ if (!value) {
+ _block = nil;
+ }
+ return value;
+}
+@end
diff --git a/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.h b/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.h
new file mode 100644
index 0000000000..1c28b158d7
--- /dev/null
+++ b/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+// This is a bridge to interact through NSEnumerator's interface with objects that only conform to
+// NSFastEnumeration. (There's nothing specifically fast about it - you certainly don't win any
+// speed by using this instead of a NSEnumerator provided by your container).
+@interface GRXNSFastEnumerator : NSEnumerator
+// After the iteration of the container (via the NSFastEnumeration protocol) is over, the container
+// is released. If the container is modified during enumeration, an exception is thrown.
+- (instancetype)initWithContainer:(id<NSFastEnumeration>)container;
+@end
diff --git a/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.m b/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.m
new file mode 100644
index 0000000000..2bbefacd69
--- /dev/null
+++ b/src/objective-c/RxLibrary/private/GRXNSFastEnumerator.m
@@ -0,0 +1,88 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXNSFastEnumerator.h"
+
+@implementation GRXNSFastEnumerator {
+ id<NSFastEnumeration> _container;
+ NSFastEnumerationState _state;
+ // Number of elements of the container currently in the _state.itemsPtr array.
+ NSUInteger _count;
+ // The index of the next object to return from the _state.itemsPtr array.
+ NSUInteger _index;
+ // A "buffer of one element," for the containers that enumerate their elements one by one. Those
+ // will set _state.itemsPtr to point to this.
+ // The NSFastEnumeration protocol requires it to be __unsafe_unretained, but that's alright
+ // because the only use we'd make of its value is to return it immediately as the result of
+ // nextObject.
+ __unsafe_unretained id _bufferValue;
+ // Neither NSEnumerator nor NSFastEnumeration instances are required to work correctly when the
+ // underlying container is mutated during iteration. The expectation is that an exception is
+ // thrown when that happens. So we check for mutations.
+ unsigned long _mutationFlag;
+ BOOL _mutationFlagIsSet;
+}
+
+- (instancetype)init {
+ return [self initWithContainer:nil];
+}
+
+// Designated initializer.
+- (instancetype)initWithContainer:(id<NSFastEnumeration>)container {
+ NSAssert(container, @"container can't be nil");
+ if ((self = [super init])) {
+ _container = container;
+ }
+ return self;
+}
+
+- (id)nextObject {
+ if (_index == _count) {
+ _index = 0;
+ _count = [_container countByEnumeratingWithState:&_state objects:&_bufferValue count:1];
+ if (_count == 0) {
+ // Enumeration is over.
+ _container = nil;
+ return nil;
+ }
+ if (_mutationFlagIsSet) {
+ NSAssert(_mutationFlag == *(_state.mutationsPtr),
+ @"container was mutated while being enumerated");
+ } else {
+ _mutationFlag = *(_state.mutationsPtr);
+ _mutationFlagIsSet = YES;
+ }
+ }
+ return _state.itemsPtr[_index++];
+}
+@end
diff --git a/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.h b/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.h
new file mode 100644
index 0000000000..5f4026e3a5
--- /dev/null
+++ b/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+// Concrete subclass of NSEnumerator whose instances return a single object before finishing.
+@interface GRXNSScalarEnumerator : NSEnumerator
+// Param value: the single object this instance will produce. After the first invocation of
+// nextObject, the value is released.
+- (instancetype)initWithValue:(id)value;
+@end
diff --git a/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.m b/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.m
new file mode 100644
index 0000000000..18f6ddfc26
--- /dev/null
+++ b/src/objective-c/RxLibrary/private/GRXNSScalarEnumerator.m
@@ -0,0 +1,57 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXNSScalarEnumerator.h"
+
+@implementation GRXNSScalarEnumerator {
+ id _value;
+}
+
+- (instancetype)init {
+ return [self initWithValue:nil];
+}
+
+// Designated initializer.
+- (instancetype)initWithValue:(id)value {
+ if ((self = [super init])) {
+ _value = value;
+ }
+ return self;
+}
+
+- (id)nextObject {
+ id value = _value;
+ _value = nil;
+ return value;
+}
+@end
diff --git a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
new file mode 100644
index 0000000000..72249b486b
--- /dev/null
+++ b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXWriter.h"
+
+// A "proxy" writer that transforms all the values of its input writer by using a mapping function.
+@interface GRXMappingWriter : GRXWriter
+- (instancetype)initWithWriter:(id<GRXWriter>)writer map:(id (^)(id value))map
+ NS_DESIGNATED_INITIALIZER;
+@end
diff --git a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
new file mode 100644
index 0000000000..8375aefdcd
--- /dev/null
+++ b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "GRXMappingWriter.h"
+
+static id (^kIdentity)(id value) = ^id(id value) {
+ return value;
+};
+
+@interface GRXWriter () <GRXWriteable>
+@end
+
+@implementation GRXMappingWriter {
+ id (^_map)(id value);
+}
+
+- (instancetype)initWithWriter:(id<GRXWriter>)writer {
+ return [self initWithWriter:writer map:nil];
+}
+
+// Designated initializer
+- (instancetype)initWithWriter:(id<GRXWriter>)writer map:(id (^)(id value))map {
+ if ((self = [super initWithWriter:writer])) {
+ _map = map ?: kIdentity;
+ }
+ return self;
+}
+
+// Override
+- (void)didReceiveValue:(id)value {
+ [super didReceiveValue:_map(value)];
+}
+@end
diff --git a/src/objective-c/examples/Sample/Podfile b/src/objective-c/examples/Sample/Podfile
new file mode 100644
index 0000000000..fa98987910
--- /dev/null
+++ b/src/objective-c/examples/Sample/Podfile
@@ -0,0 +1,12 @@
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+
+pod 'RxLibrary', :path => "../../RxLibrary"
+
+target 'Sample' do
+
+end
+
+target 'SampleTests' do
+
+end
diff --git a/src/objective-c/examples/Sample/Podfile.lock b/src/objective-c/examples/Sample/Podfile.lock
new file mode 100644
index 0000000000..fee4b43bec
--- /dev/null
+++ b/src/objective-c/examples/Sample/Podfile.lock
@@ -0,0 +1,14 @@
+PODS:
+ - RxLibrary (0.0.1)
+
+DEPENDENCIES:
+ - RxLibrary (from `../../RxLibrary`)
+
+EXTERNAL SOURCES:
+ RxLibrary:
+ :path: ../../RxLibrary
+
+SPEC CHECKSUMS:
+ RxLibrary: 70cfcf1573ec16a375b4fe61d976a3188aab9303
+
+COCOAPODS: 0.35.0
diff --git a/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXImmediateWriter.h b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXImmediateWriter.h
new file mode 120000
index 0000000000..915b0e4f90
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXImmediateWriter.h
@@ -0,0 +1 @@
+../../../../../../RxLibrary/GRXImmediateWriter.h \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXMappingWriter.h b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXMappingWriter.h
new file mode 120000
index 0000000000..4d1073f451
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXMappingWriter.h
@@ -0,0 +1 @@
+../../../../../../RxLibrary/transformations/GRXMappingWriter.h \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriteable.h b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriteable.h
new file mode 120000
index 0000000000..cb275199fc
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriteable.h
@@ -0,0 +1 @@
+../../../../../../RxLibrary/GRXWriteable.h \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Immediate.h b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Immediate.h
new file mode 120000
index 0000000000..fe5e740afb
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Immediate.h
@@ -0,0 +1 @@
+../../../../../../RxLibrary/GRXWriter+Immediate.h \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Transformations.h b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Transformations.h
new file mode 120000
index 0000000000..c57168c9ef
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Transformations.h
@@ -0,0 +1 @@
+../../../../../../RxLibrary/GRXWriter+Transformations.h \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter.h b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter.h
new file mode 120000
index 0000000000..c4f657e567
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter.h
@@ -0,0 +1 @@
+../../../../../../RxLibrary/GRXWriter.h \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/NSEnumerator+GRXUtil.h b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/NSEnumerator+GRXUtil.h
new file mode 120000
index 0000000000..97c6aaeeec
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/NSEnumerator+GRXUtil.h
@@ -0,0 +1 @@
+../../../../../../RxLibrary/NSEnumerator+GRXUtil.h \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Local Podspecs/RxLibrary.podspec b/src/objective-c/examples/Sample/Pods/Local Podspecs/RxLibrary.podspec
new file mode 100644
index 0000000000..605aedaf10
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Local Podspecs/RxLibrary.podspec
@@ -0,0 +1,13 @@
+Pod::Spec.new do |s|
+ s.name = 'RxLibrary'
+ s.version = '0.0.1'
+ s.summary = 'Reactive Extensions library for iOS'
+ s.author = {
+ 'Jorge Canizales' => 'jcanizales@google.com'
+ }
+ s.source_files = '*.{h,m}', 'transformations/*.{h,m}', 'private/*.{h,m}'
+ s.private_header_files = 'private/*.h'
+ s.platform = :ios
+ s.ios.deployment_target = '6.0'
+ s.requires_arc = true
+end
diff --git a/src/objective-c/examples/Sample/Pods/Manifest.lock b/src/objective-c/examples/Sample/Pods/Manifest.lock
new file mode 100644
index 0000000000..fee4b43bec
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Manifest.lock
@@ -0,0 +1,14 @@
+PODS:
+ - RxLibrary (0.0.1)
+
+DEPENDENCIES:
+ - RxLibrary (from `../../RxLibrary`)
+
+EXTERNAL SOURCES:
+ RxLibrary:
+ :path: ../../RxLibrary
+
+SPEC CHECKSUMS:
+ RxLibrary: 70cfcf1573ec16a375b4fe61d976a3188aab9303
+
+COCOAPODS: 0.35.0
diff --git a/src/objective-c/examples/Sample/Pods/Pods.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Pods/Pods.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..68290dd5e8
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Pods.xcodeproj/project.pbxproj
@@ -0,0 +1,2888 @@
+<?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>archiveVersion</key>
+ <string>1</string>
+ <key>classes</key>
+ <dict/>
+ <key>objectVersion</key>
+ <string>46</string>
+ <key>objects</key>
+ <dict>
+ <key>00949E44051CD97851DEFF3B</key>
+ <dict>
+ <key>fileRef</key>
+ <string>9CFAC09E370EA1C96C8D2880</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>01F5B724A99ADB3547023C72</key>
+ <dict>
+ <key>fileRef</key>
+ <string>1868370C0050315A6B835D42</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>0239F1B46D24E21A8042F47F</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>8919AE774852DD128A7CB510</string>
+ <key>buildPhases</key>
+ <array>
+ <string>A71CC1B520D2DFF451839FE2</string>
+ <string>896F697BD1BEAF8A081337EB</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array>
+ <string>6EB14BC96525C955FBD5CC75</string>
+ </array>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>Pods-Sample</string>
+ <key>productName</key>
+ <string>Pods-Sample</string>
+ <key>productReference</key>
+ <string>DF94410F5DC0A0AB69336DF4</string>
+ <key>productType</key>
+ <string>com.apple.product-type.library.static</string>
+ </dict>
+ <key>024F840533A6674922DB7899</key>
+ <dict>
+ <key>fileRef</key>
+ <string>46513F4AD14CBD2377C1E7A1</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>0260773D27B4AE159FB0B22D</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>GRXWriter+Immediate.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>026236C3432E9DBC10A40748</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>Pods-SampleTests-dummy.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>0385BCBCA0601E80FAD2A901</key>
+ <dict>
+ <key>fileRef</key>
+ <string>46513F4AD14CBD2377C1E7A1</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>0879DBE6FFA1852D106330B4</key>
+ <dict>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>CLANG_CXX_LANGUAGE_STANDARD</key>
+ <string>gnu++0x</string>
+ <key>CLANG_CXX_LIBRARY</key>
+ <string>libc++</string>
+ <key>CLANG_ENABLE_MODULES</key>
+ <string>YES</string>
+ <key>CLANG_ENABLE_OBJC_ARC</key>
+ <string>YES</string>
+ <key>CLANG_WARN_BOOL_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_CONSTANT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_DIRECT_OBJC_ISA_USAGE</key>
+ <string>YES</string>
+ <key>CLANG_WARN_EMPTY_BODY</key>
+ <string>YES</string>
+ <key>CLANG_WARN_ENUM_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_INT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_OBJC_ROOT_CLASS</key>
+ <string>YES</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>GCC_C_LANGUAGE_STANDARD</key>
+ <string>gnu99</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>GCC_WARN_64_TO_32_BIT_CONVERSION</key>
+ <string>YES</string>
+ <key>GCC_WARN_ABOUT_RETURN_TYPE</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNDECLARED_SELECTOR</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNINITIALIZED_AUTOS</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNUSED_FUNCTION</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNUSED_VARIABLE</key>
+ <string>YES</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>ONLY_ACTIVE_ARCH</key>
+ <string>YES</string>
+ <key>STRIP_INSTALLED_PRODUCT</key>
+ <string>NO</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>092D0456252ED3F90F66084D</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>Pods-Sample-environment.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>0BC8818D3A097831FDE0750B</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BC50D76123DA4B85E6AD77B4</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>0C57EED724EBF58759F9F6DF</key>
+ <dict>
+ <key>fileRef</key>
+ <string>4BB75B0FC7359E8EA8672954</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>0D09CEB9308FA5BACEB5F84C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>30063D2979A72CA1050BD4A6</string>
+ <string>DB3528F609E6177E1C5A691C</string>
+ <string>026236C3432E9DBC10A40748</string>
+ <string>EF8B807C5A2059D6C709450D</string>
+ <string>8B503889F903CED9A12E5C87</string>
+ <string>591702CE7D8AF91674F1640F</string>
+ <string>DB677464758307786D68CCE9</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Pods-SampleTests</string>
+ <key>path</key>
+ <string>Target Support Files/Pods-SampleTests</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>0D53085043D992DC00E29F0A</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>GRXWriteable.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>0F20828B67FDCB990B1818E9</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>DB677464758307786D68CCE9</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_CFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_CPLUSPLUSFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>11072993378724E9AF9CAF85</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>archive.ar</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>libPods-SampleTests-RxLibrary.a</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>1146D04C598DEBA045C96C2F</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>1F3162E71EE5AA2B65DEC06D</string>
+ </array>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>114F64D42E2AF2F3EBDE9BCB</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>1D31B6F63B148D2EA5637823</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>124B93EFC16A2026269840B2</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXTargetDependency</string>
+ <key>name</key>
+ <string>Pods-RxLibrary</string>
+ <key>target</key>
+ <string>6BFD156F312F6CAA1E5B00CA</string>
+ <key>targetProxy</key>
+ <string>DB007D27F74F8F72C72A1079</string>
+ </dict>
+ <key>14D92BB2ED12213381BD2EB9</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>C4342DDEEF3C3290956C21DF</string>
+ <key>buildPhases</key>
+ <array>
+ <string>432AE81157886BE484236751</string>
+ <string>87700F015FA41F53D88CA4BC</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array>
+ <string>F8B4778EF3030EEC2E9927CE</string>
+ </array>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>Pods-SampleTests</string>
+ <key>productName</key>
+ <string>Pods-SampleTests</string>
+ <key>productReference</key>
+ <string>42A375125393D0613249D046</string>
+ <key>productType</key>
+ <string>com.apple.product-type.library.static</string>
+ </dict>
+ <key>15DC9A153BC412DB41B7F154</key>
+ <dict>
+ <key>fileRef</key>
+ <string>5AEFA85A5F1AD206D68B0576</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>15F64D3D7D10DB47599A72EB</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>name</key>
+ <string>GRXMappingWriter.m</string>
+ <key>path</key>
+ <string>transformations/GRXMappingWriter.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>16E6BBD46D9745611EF313FB</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BECFE3DCB323841851972996</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>17F4C2F25813E7A4588FF233</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>B153046F0CBA526564A9673C</string>
+ <string>B960FF1BE77D3F4459EEB1E0</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>1868370C0050315A6B835D42</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>name</key>
+ <string>GRXNSScalarEnumerator.h</string>
+ <key>path</key>
+ <string>private/GRXNSScalarEnumerator.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>19001096C873023095C4F032</key>
+ <dict>
+ <key>fileRef</key>
+ <string>EB29FAB1F81F0D17BDAD72D0</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>1B8264EEFEF4AD585182D256</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods-Sample.debug.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>1C8DFDF9C457D910DC1FD227</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>Pods-environment.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>1D31B6F63B148D2EA5637823</key>
+ <dict>
+ <key>fileRef</key>
+ <string>22DB20D833E7D26AEA6513D6</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>1E5420835E4862DBA55002A9</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BECFE3DCB323841851972996</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>1F3162E71EE5AA2B65DEC06D</key>
+ <dict>
+ <key>fileRef</key>
+ <string>56CE61A20C6F88CC0CE888C8</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>22531AF83592134D3879C3E1</key>
+ <dict>
+ <key>fileRef</key>
+ <string>15F64D3D7D10DB47599A72EB</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>22DB20D833E7D26AEA6513D6</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>Pods-dummy.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>245F9E9690E6E08D291FC94C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BC52B0661F25B25CE382296C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>266008D38F1E72755C711699</key>
+ <dict>
+ <key>fileRef</key>
+ <string>026236C3432E9DBC10A40748</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2663F4401A9075DAC0B24171</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>Pods-RxLibrary-dummy.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>26E6ACBF137DBC325B4E7DA7</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>B05A2B15C8A03AABA163D7D7</string>
+ <key>buildPhases</key>
+ <array>
+ <string>114F64D42E2AF2F3EBDE9BCB</string>
+ <string>DCAB71BD665AF17533987B69</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array>
+ <string>124B93EFC16A2026269840B2</string>
+ </array>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>Pods</string>
+ <key>productName</key>
+ <string>Pods</string>
+ <key>productReference</key>
+ <string>5C30ABB95D604B483422D72A</string>
+ <key>productType</key>
+ <string>com.apple.product-type.library.static</string>
+ </dict>
+ <key>27E123435067CC11FE103999</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods-Sample.release.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>288A25371032891C824CF4AA</key>
+ <dict>
+ <key>fileRef</key>
+ <string>838341407CEBBFB19D25C45A</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>29B274FDF882AB8B39814FE6</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>687D79F4C2484F58E9796051</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREFIX_HEADER</key>
+ <string>Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>2AADA4C52A284ED5D41C7CF5</key>
+ <dict>
+ <key>fileRef</key>
+ <string>0D53085043D992DC00E29F0A</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2B05A4C21D00E8CF0DE88447</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>name</key>
+ <string>Pods-SampleTests-RxLibrary-prefix.pch</string>
+ <key>path</key>
+ <string>../Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>2B341576464148A01DCFB28B</key>
+ <dict>
+ <key>fileRef</key>
+ <string>3AD75C69A61408EF8BE0F247</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2B49DCA723ECBC0F2777B960</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BC52B0661F25B25CE382296C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2D6833D4D544AC13450405B1</key>
+ <dict>
+ <key>fileRef</key>
+ <string>2663F4401A9075DAC0B24171</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2D7732FBE1A5A7FC42D4DC4B</key>
+ <dict>
+ <key>fileRef</key>
+ <string>56CE61A20C6F88CC0CE888C8</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2DA405F6E578008991B3F9EA</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BECFE3DCB323841851972996</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2F91A2AD622F87D98C9B0E1E</key>
+ <dict>
+ <key>fileRef</key>
+ <string>0D53085043D992DC00E29F0A</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>2FE1D288B8389F925AA3CE0C</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods-RxLibrary-Private.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>30063D2979A72CA1050BD4A6</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text</string>
+ <key>path</key>
+ <string>Pods-SampleTests-acknowledgements.markdown</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>3133D1CCCF4F1FE3E893509C</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods-RxLibrary.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>352B4C7135E3BBBFEBAB7F55</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BA9F62DDE37FF0D601A4D5EA</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>355670384FC160AB6C32765E</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>56CE61A20C6F88CC0CE888C8</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>iOS</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>36C139FD3DEDB8CA2A1D3295</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text</string>
+ <key>path</key>
+ <string>Pods-acknowledgements.markdown</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>36FF37EAC7E918C4CD867776</key>
+ <dict>
+ <key>fileRef</key>
+ <string>EB29FAB1F81F0D17BDAD72D0</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>3749A34D3DFA6E2F3539E546</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>0879DBE6FFA1852D106330B4</string>
+ <string>6B88B9AB87714A903970EAED</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>3800855A656C8D0813062074</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>9508723D4C0D4321A5188108</string>
+ <key>buildPhases</key>
+ <array>
+ <string>F779618174957BE31FCCDE56</string>
+ <string>45FC41033EB61B16BC8151B9</string>
+ <string>8AB7020D9B71B1B4F34249BE</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>Pods-SampleTests-RxLibrary</string>
+ <key>productName</key>
+ <string>Pods-SampleTests-RxLibrary</string>
+ <key>productReference</key>
+ <string>11072993378724E9AF9CAF85</string>
+ <key>productType</key>
+ <string>com.apple.product-type.library.static</string>
+ </dict>
+ <key>397A12919FB4BDD608FE207C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>B4FB10339A6A2E1AAF255802</string>
+ <string>5840BDD08ED67C12ADB1DF08</string>
+ <string>817F8B2E38A51910E8F8EC7D</string>
+ <string>8B05D39455D5B23720961FA4</string>
+ <string>F2BB78774BCEFD5DDDF38239</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>3A4DE73D0D0274E782C1A564</key>
+ <dict>
+ <key>fileRef</key>
+ <string>56CE61A20C6F88CC0CE888C8</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>3AD75C69A61408EF8BE0F247</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>GRXWriteable.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>3C3F1A188E25219C230FFD4F</key>
+ <dict>
+ <key>fileRef</key>
+ <string>9DADE0CF857B717294F7F74F</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>404D4F98249F3383235463A4</key>
+ <dict>
+ <key>fileRef</key>
+ <string>56CE61A20C6F88CC0CE888C8</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>407E794549893DD91A2ED84E</key>
+ <dict>
+ <key>fileRef</key>
+ <string>DB0257E62EC33F3F316EF017</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>42A375125393D0613249D046</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>archive.ar</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>libPods-SampleTests.a</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>42B461F095E85911637DFD60</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>name</key>
+ <string>Pods-SampleTests-RxLibrary-dummy.m</string>
+ <key>path</key>
+ <string>../Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-dummy.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>432AE81157886BE484236751</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>266008D38F1E72755C711699</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>43CC797FB2A733DF5B7A9F05</key>
+ <dict>
+ <key>fileRef</key>
+ <string>15F64D3D7D10DB47599A72EB</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>458FF1EEF4EB9646C699F3DD</key>
+ <dict>
+ <key>fileRef</key>
+ <string>57AC9BF19B9635D7476CA5FA</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>45A1913C8F48686C1FC82520</key>
+ <dict>
+ <key>fileRef</key>
+ <string>9DADE0CF857B717294F7F74F</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>45FC41033EB61B16BC8151B9</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>2D7732FBE1A5A7FC42D4DC4B</string>
+ </array>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>46513F4AD14CBD2377C1E7A1</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>name</key>
+ <string>GRXNSFastEnumerator.h</string>
+ <key>path</key>
+ <string>private/GRXNSFastEnumerator.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>46A8EFCC59CF17E048EC34ED</key>
+ <dict>
+ <key>fileRef</key>
+ <string>5AEFA85A5F1AD206D68B0576</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>46FAFA88CA3E774263422EB9</key>
+ <dict>
+ <key>fileRef</key>
+ <string>3AD75C69A61408EF8BE0F247</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>4946B2D315E9BF5CBACD7D52</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.plist.xml</string>
+ <key>path</key>
+ <string>Pods-acknowledgements.plist</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>4954E8CE730737CD2991E502</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>BECFE3DCB323841851972996</string>
+ <string>BC52B0661F25B25CE382296C</string>
+ <string>9CFAC09E370EA1C96C8D2880</string>
+ <string>15F64D3D7D10DB47599A72EB</string>
+ <string>5AEFA85A5F1AD206D68B0576</string>
+ <string>4BB75B0FC7359E8EA8672954</string>
+ <string>46513F4AD14CBD2377C1E7A1</string>
+ <string>636AC1003F2C71FFD74542CD</string>
+ <string>1868370C0050315A6B835D42</string>
+ <string>57AC9BF19B9635D7476CA5FA</string>
+ <string>0D53085043D992DC00E29F0A</string>
+ <string>3AD75C69A61408EF8BE0F247</string>
+ <string>DB0257E62EC33F3F316EF017</string>
+ <string>BDA58E5E1AE450540A2B0227</string>
+ <string>0260773D27B4AE159FB0B22D</string>
+ <string>EB29FAB1F81F0D17BDAD72D0</string>
+ <string>838341407CEBBFB19D25C45A</string>
+ <string>F763F3DF1B47888E75D0ED9C</string>
+ <string>9DADE0CF857B717294F7F74F</string>
+ <string>BA9F62DDE37FF0D601A4D5EA</string>
+ <string>D49849E96C0C5FFB93C810CD</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>RxLibrary</string>
+ <key>path</key>
+ <string>../../../RxLibrary</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>4972C151CE9A8A15BC1AE2C8</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>name</key>
+ <string>Pods-Sample-RxLibrary-prefix.pch</string>
+ <key>path</key>
+ <string>../Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>4BB47C74830C63C90981278E</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>245F9E9690E6E08D291FC94C</string>
+ <string>A96854FB48432263FE68C313</string>
+ <string>AA52EF1CD8A3683472BD86FE</string>
+ <string>BB88043BB37FC0261BA90A30</string>
+ <string>54A02FC8DA14CEC49EA8C8D5</string>
+ <string>B7902691B66134F3764663D9</string>
+ <string>19001096C873023095C4F032</string>
+ <string>E86A17CE1D79ECDCEBF91109</string>
+ <string>8BB6B6B3653FC309CB8EB3A0</string>
+ <string>7BBF3F432525D33FCB074BD5</string>
+ <string>2D6833D4D544AC13450405B1</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>4BB75B0FC7359E8EA8672954</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>name</key>
+ <string>GRXNSBlockEnumerator.m</string>
+ <key>path</key>
+ <string>private/GRXNSBlockEnumerator.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>50FF607D5DA961C6BEF4ABAC</key>
+ <dict>
+ <key>fileRef</key>
+ <string>838341407CEBBFB19D25C45A</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>5280A583CA6C6C66698AE67C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>DB0257E62EC33F3F316EF017</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>54A02FC8DA14CEC49EA8C8D5</key>
+ <dict>
+ <key>fileRef</key>
+ <string>57AC9BF19B9635D7476CA5FA</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>56CE61A20C6F88CC0CE888C8</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>wrapper.framework</string>
+ <key>name</key>
+ <string>Foundation.framework</string>
+ <key>path</key>
+ <string>Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/Foundation.framework</string>
+ <key>sourceTree</key>
+ <string>DEVELOPER_DIR</string>
+ </dict>
+ <key>57AC9BF19B9635D7476CA5FA</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>name</key>
+ <string>GRXNSScalarEnumerator.m</string>
+ <key>path</key>
+ <string>private/GRXNSScalarEnumerator.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>5840BDD08ED67C12ADB1DF08</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>4954E8CE730737CD2991E502</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Development Pods</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>591702CE7D8AF91674F1640F</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods-SampleTests.debug.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>594F98D43B96AB5C11E61C10</key>
+ <dict>
+ <key>fileRef</key>
+ <string>F763F3DF1B47888E75D0ED9C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>5AEFA85A5F1AD206D68B0576</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>name</key>
+ <string>GRXNSBlockEnumerator.h</string>
+ <key>path</key>
+ <string>private/GRXNSBlockEnumerator.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>5B8A3BFE016346EF080D52C6</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>3A4DE73D0D0274E782C1A564</string>
+ </array>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>5C30ABB95D604B483422D72A</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>archive.ar</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>libPods.a</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>5DE93D7B39D2D1AD7336C4AC</key>
+ <dict>
+ <key>fileRef</key>
+ <string>838341407CEBBFB19D25C45A</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>621587D6C7759FBE7096D185</key>
+ <dict>
+ <key>fileRef</key>
+ <string>46513F4AD14CBD2377C1E7A1</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>636AC1003F2C71FFD74542CD</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>name</key>
+ <string>GRXNSFastEnumerator.m</string>
+ <key>path</key>
+ <string>private/GRXNSFastEnumerator.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>687D79F4C2484F58E9796051</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>name</key>
+ <string>Pods-SampleTests-RxLibrary-Private.xcconfig</string>
+ <key>path</key>
+ <string>../Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-Private.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>69E8FF71552D08D72B9068F1</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>36C139FD3DEDB8CA2A1D3295</string>
+ <string>4946B2D315E9BF5CBACD7D52</string>
+ <string>22DB20D833E7D26AEA6513D6</string>
+ <string>1C8DFDF9C457D910DC1FD227</string>
+ <string>E14CB6F332A9E58BB5F76C07</string>
+ <string>6AC13D00A5A61BDA0DE5FAAF</string>
+ <string>A577CB571492B4F951064FCF</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Pods</string>
+ <key>path</key>
+ <string>Target Support Files/Pods</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6AC13D00A5A61BDA0DE5FAAF</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods.debug.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6B5B56ED61BE76782DF02817</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>687D79F4C2484F58E9796051</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREFIX_HEADER</key>
+ <string>Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_CFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_CPLUSPLUSFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>6B88B9AB87714A903970EAED</key>
+ <dict>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>CLANG_CXX_LANGUAGE_STANDARD</key>
+ <string>gnu++0x</string>
+ <key>CLANG_CXX_LIBRARY</key>
+ <string>libc++</string>
+ <key>CLANG_ENABLE_MODULES</key>
+ <string>YES</string>
+ <key>CLANG_ENABLE_OBJC_ARC</key>
+ <string>YES</string>
+ <key>CLANG_WARN_BOOL_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_CONSTANT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_DIRECT_OBJC_ISA_USAGE</key>
+ <string>YES</string>
+ <key>CLANG_WARN_EMPTY_BODY</key>
+ <string>YES</string>
+ <key>CLANG_WARN_ENUM_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_INT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_OBJC_ROOT_CLASS</key>
+ <string>YES</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>ENABLE_NS_ASSERTIONS</key>
+ <string>NO</string>
+ <key>GCC_C_LANGUAGE_STANDARD</key>
+ <string>gnu99</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>RELEASE=1</string>
+ </array>
+ <key>GCC_WARN_64_TO_32_BIT_CONVERSION</key>
+ <string>YES</string>
+ <key>GCC_WARN_ABOUT_RETURN_TYPE</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNDECLARED_SELECTOR</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNINITIALIZED_AUTOS</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNUSED_FUNCTION</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNUSED_VARIABLE</key>
+ <string>YES</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>STRIP_INSTALLED_PRODUCT</key>
+ <string>NO</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>6BFD156F312F6CAA1E5B00CA</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>962FF5FAC21292530C615D05</string>
+ <key>buildPhases</key>
+ <array>
+ <string>4BB47C74830C63C90981278E</string>
+ <string>5B8A3BFE016346EF080D52C6</string>
+ <string>A4C1C82F355864E7D3E200DD</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>Pods-RxLibrary</string>
+ <key>productName</key>
+ <string>Pods-RxLibrary</string>
+ <key>productReference</key>
+ <string>A579EC5BE7E68C55CA5FECDE</string>
+ <key>productType</key>
+ <string>com.apple.product-type.library.static</string>
+ </dict>
+ <key>6D1D41BAE4E325572FAC7B17</key>
+ <dict>
+ <key>fileRef</key>
+ <string>9DADE0CF857B717294F7F74F</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6E00FD6D197F0D1332D11199</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>1B8264EEFEF4AD585182D256</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>6E0669CB3E76E19FC854BA74</key>
+ <dict>
+ <key>fileRef</key>
+ <string>4BB75B0FC7359E8EA8672954</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6EB14BC96525C955FBD5CC75</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXTargetDependency</string>
+ <key>name</key>
+ <string>Pods-Sample-RxLibrary</string>
+ <key>target</key>
+ <string>F6C59E5B4CFE053E9F98000E</string>
+ <key>targetProxy</key>
+ <string>A0215878A7EC41E833B5F1D2</string>
+ </dict>
+ <key>74F28D2155D125C3068F96BE</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>6AC13D00A5A61BDA0DE5FAAF</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>7A8627E1649F66DEE014EB46</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>D53A8F2B11E6C2C187AFFF1D</string>
+ <string>B50ECED4CEC7554ED6077619</string>
+ <string>BC50D76123DA4B85E6AD77B4</string>
+ <string>092D0456252ED3F90F66084D</string>
+ <string>AA99564782B655791B053E58</string>
+ <string>1B8264EEFEF4AD585182D256</string>
+ <string>27E123435067CC11FE103999</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Pods-Sample</string>
+ <key>path</key>
+ <string>Target Support Files/Pods-Sample</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>7AC4B3F3D7BB132642153A38</key>
+ <dict>
+ <key>fileRef</key>
+ <string>0260773D27B4AE159FB0B22D</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>7BBF3F432525D33FCB074BD5</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BA9F62DDE37FF0D601A4D5EA</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>7DA2A517A18D85B390FB122A</key>
+ <dict>
+ <key>containerPortal</key>
+ <string>FBF79DDF04ADEAED54BA2286</string>
+ <key>isa</key>
+ <string>PBXContainerItemProxy</string>
+ <key>proxyType</key>
+ <string>1</string>
+ <key>remoteGlobalIDString</key>
+ <string>3800855A656C8D0813062074</string>
+ <key>remoteInfo</key>
+ <string>Pods-SampleTests-RxLibrary</string>
+ </dict>
+ <key>7E9B63EFA2466C4456A0695A</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>2FE1D288B8389F925AA3CE0C</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREFIX_HEADER</key>
+ <string>Target Support Files/Pods-RxLibrary/Pods-RxLibrary-prefix.pch</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_CFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_CPLUSPLUSFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>7FACBF2C8AF0403DD1C11015</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>name</key>
+ <string>Pods-Sample-RxLibrary-Private.xcconfig</string>
+ <key>path</key>
+ <string>../Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-Private.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>801BBA7A538CFAE6746966A7</key>
+ <dict>
+ <key>fileRef</key>
+ <string>42B461F095E85911637DFD60</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>817F8B2E38A51910E8F8EC7D</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>355670384FC160AB6C32765E</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Frameworks</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>838341407CEBBFB19D25C45A</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>GRXWriter+Transformations.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>85D5565EC08D14A6A60F1DDA</key>
+ <dict>
+ <key>fileRef</key>
+ <string>56CE61A20C6F88CC0CE888C8</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>86586E0B51D3DC6A97D0A7F3</key>
+ <dict>
+ <key>fileRef</key>
+ <string>56CE61A20C6F88CC0CE888C8</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>86D03B997B81819E2F39E48B</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BC52B0661F25B25CE382296C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>87700F015FA41F53D88CA4BC</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>404D4F98249F3383235463A4</string>
+ </array>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>8915073BE8158EF53FE11B95</key>
+ <dict>
+ <key>fileRef</key>
+ <string>EB29FAB1F81F0D17BDAD72D0</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>8919AE774852DD128A7CB510</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>6E00FD6D197F0D1332D11199</string>
+ <string>B602CFEF970BEA98E40A056C</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>896F697BD1BEAF8A081337EB</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>86586E0B51D3DC6A97D0A7F3</string>
+ </array>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>8A7375A2F98889F35C15E2D7</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>name</key>
+ <string>Pods-SampleTests-RxLibrary.xcconfig</string>
+ <key>path</key>
+ <string>../Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>8AB7020D9B71B1B4F34249BE</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>1E5420835E4862DBA55002A9</string>
+ <string>00949E44051CD97851DEFF3B</string>
+ <string>15DC9A153BC412DB41B7F154</string>
+ <string>0385BCBCA0601E80FAD2A901</string>
+ <string>01F5B724A99ADB3547023C72</string>
+ <string>F2C6AACFE46FFA8DC383DE43</string>
+ <string>7AC4B3F3D7BB132642153A38</string>
+ <string>5DE93D7B39D2D1AD7336C4AC</string>
+ <string>407E794549893DD91A2ED84E</string>
+ <string>3C3F1A188E25219C230FFD4F</string>
+ </array>
+ <key>isa</key>
+ <string>PBXHeadersBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>8B05D39455D5B23720961FA4</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>5C30ABB95D604B483422D72A</string>
+ <string>A579EC5BE7E68C55CA5FECDE</string>
+ <string>DF94410F5DC0A0AB69336DF4</string>
+ <string>EF2EE4BC906FF9909348DAB5</string>
+ <string>42A375125393D0613249D046</string>
+ <string>11072993378724E9AF9CAF85</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Products</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>8B503889F903CED9A12E5C87</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.script.sh</string>
+ <key>path</key>
+ <string>Pods-SampleTests-resources.sh</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>8BB6B6B3653FC309CB8EB3A0</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BDA58E5E1AE450540A2B0227</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>8CD061F02F905957F4C1D188</key>
+ <dict>
+ <key>fileRef</key>
+ <string>636AC1003F2C71FFD74542CD</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>911BEE248BE640294A081862</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>Pods-RxLibrary-prefix.pch</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>9508723D4C0D4321A5188108</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>29B274FDF882AB8B39814FE6</string>
+ <string>6B5B56ED61BE76782DF02817</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>962FF5FAC21292530C615D05</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>A150782D73BBE95DE629B03C</string>
+ <string>7E9B63EFA2466C4456A0695A</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>9BD773E928AD698D23B20123</key>
+ <dict>
+ <key>fileRef</key>
+ <string>1868370C0050315A6B835D42</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>9CCBE9A628C305B3B089B8DD</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BA9F62DDE37FF0D601A4D5EA</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>9CFAC09E370EA1C96C8D2880</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>name</key>
+ <string>GRXMappingWriter.h</string>
+ <key>path</key>
+ <string>transformations/GRXMappingWriter.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>9DADE0CF857B717294F7F74F</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>NSEnumerator+GRXUtil.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>9E8DC61269B141639DA7F859</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>16E6BBD46D9745611EF313FB</string>
+ <string>CC0A03D531EF0FF199671820</string>
+ <string>C382F416EFA39BE2CF216044</string>
+ <string>621587D6C7759FBE7096D185</string>
+ <string>C0AC333A6FE8F07600C96890</string>
+ <string>2F91A2AD622F87D98C9B0E1E</string>
+ <string>FDC6B84EAC9989F0827EA4F3</string>
+ <string>50FF607D5DA961C6BEF4ABAC</string>
+ <string>5280A583CA6C6C66698AE67C</string>
+ <string>6D1D41BAE4E325572FAC7B17</string>
+ </array>
+ <key>isa</key>
+ <string>PBXHeadersBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>A00077019C113466960E9DAF</key>
+ <dict>
+ <key>fileRef</key>
+ <string>9CFAC09E370EA1C96C8D2880</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>A0215878A7EC41E833B5F1D2</key>
+ <dict>
+ <key>containerPortal</key>
+ <string>FBF79DDF04ADEAED54BA2286</string>
+ <key>isa</key>
+ <string>PBXContainerItemProxy</string>
+ <key>proxyType</key>
+ <string>1</string>
+ <key>remoteGlobalIDString</key>
+ <string>F6C59E5B4CFE053E9F98000E</string>
+ <key>remoteInfo</key>
+ <string>Pods-Sample-RxLibrary</string>
+ </dict>
+ <key>A150782D73BBE95DE629B03C</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>2FE1D288B8389F925AA3CE0C</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREFIX_HEADER</key>
+ <string>Target Support Files/Pods-RxLibrary/Pods-RxLibrary-prefix.pch</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>A4C1C82F355864E7D3E200DD</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>2DA405F6E578008991B3F9EA</string>
+ <string>A00077019C113466960E9DAF</string>
+ <string>46A8EFCC59CF17E048EC34ED</string>
+ <string>024F840533A6674922DB7899</string>
+ <string>9BD773E928AD698D23B20123</string>
+ <string>2AADA4C52A284ED5D41C7CF5</string>
+ <string>CC358E38AE146C095C401760</string>
+ <string>288A25371032891C824CF4AA</string>
+ <string>FDC939796E70DC7D141E29FC</string>
+ <string>45A1913C8F48686C1FC82520</string>
+ </array>
+ <key>isa</key>
+ <string>PBXHeadersBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>A577CB571492B4F951064FCF</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods.release.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>A579EC5BE7E68C55CA5FECDE</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>archive.ar</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>libPods-RxLibrary.a</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>A71CC1B520D2DFF451839FE2</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>0BC8818D3A097831FDE0750B</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>A8AFEFDF4700447BBCDF9E10</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>591702CE7D8AF91674F1640F</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>A96854FB48432263FE68C313</key>
+ <dict>
+ <key>fileRef</key>
+ <string>15F64D3D7D10DB47599A72EB</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>AA52EF1CD8A3683472BD86FE</key>
+ <dict>
+ <key>fileRef</key>
+ <string>4BB75B0FC7359E8EA8672954</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>AA99564782B655791B053E58</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.script.sh</string>
+ <key>path</key>
+ <string>Pods-Sample-resources.sh</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>AF9F0D991C2913F55496D06E</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>A577CB571492B4F951064FCF</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_CFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_CPLUSPLUSFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>B034EE43C1EF96D1CBD1328A</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>name</key>
+ <string>Pods-Sample-RxLibrary.xcconfig</string>
+ <key>path</key>
+ <string>../Pods-Sample-RxLibrary/Pods-Sample-RxLibrary.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>B05A2B15C8A03AABA163D7D7</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>74F28D2155D125C3068F96BE</string>
+ <string>AF9F0D991C2913F55496D06E</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>B153046F0CBA526564A9673C</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>7FACBF2C8AF0403DD1C11015</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREFIX_HEADER</key>
+ <string>Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>B4FB10339A6A2E1AAF255802</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text</string>
+ <key>name</key>
+ <string>Podfile</string>
+ <key>path</key>
+ <string>../Podfile</string>
+ <key>sourceTree</key>
+ <string>SOURCE_ROOT</string>
+ <key>xcLanguageSpecificationIdentifier</key>
+ <string>xcode.lang.ruby</string>
+ </dict>
+ <key>B50ECED4CEC7554ED6077619</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.plist.xml</string>
+ <key>path</key>
+ <string>Pods-Sample-acknowledgements.plist</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>B602CFEF970BEA98E40A056C</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>27E123435067CC11FE103999</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_CFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_CPLUSPLUSFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>B78477CA74AEFC96C25B49B4</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BDA58E5E1AE450540A2B0227</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>B7902691B66134F3764663D9</key>
+ <dict>
+ <key>fileRef</key>
+ <string>3AD75C69A61408EF8BE0F247</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>B90592E4E39AFD1E769F9A95</key>
+ <dict>
+ <key>fileRef</key>
+ <string>F763F3DF1B47888E75D0ED9C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>B960FF1BE77D3F4459EEB1E0</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>7FACBF2C8AF0403DD1C11015</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>DSTROOT</key>
+ <string>/tmp/xcodeproj.dst</string>
+ <key>GCC_PRECOMPILE_PREFIX_HEADER</key>
+ <string>YES</string>
+ <key>GCC_PREFIX_HEADER</key>
+ <string>Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch</string>
+ <key>INSTALL_PATH</key>
+ <string>$(BUILT_PRODUCTS_DIR)</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.0</string>
+ <key>OTHER_CFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_CPLUSPLUSFLAGS</key>
+ <array>
+ <string>-DNS_BLOCK_ASSERTIONS=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>OTHER_LDFLAGS</key>
+ <string></string>
+ <key>OTHER_LIBTOOLFLAGS</key>
+ <string></string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>PUBLIC_HEADERS_FOLDER_PATH</key>
+ <string>$(TARGET_NAME)</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>SKIP_INSTALL</key>
+ <string>YES</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>BA9F62DDE37FF0D601A4D5EA</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>NSEnumerator+GRXUtil.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>BB88043BB37FC0261BA90A30</key>
+ <dict>
+ <key>fileRef</key>
+ <string>636AC1003F2C71FFD74542CD</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>BC50D76123DA4B85E6AD77B4</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>Pods-Sample-dummy.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>BC52B0661F25B25CE382296C</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>GRXImmediateWriter.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>BDA58E5E1AE450540A2B0227</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>GRXWriter.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>BECFE3DCB323841851972996</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>GRXImmediateWriter.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>BFE770FF3C0847AB995A82CA</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>86D03B997B81819E2F39E48B</string>
+ <string>43CC797FB2A733DF5B7A9F05</string>
+ <string>6E0669CB3E76E19FC854BA74</string>
+ <string>CBA4FEEF7E642535FB39D878</string>
+ <string>FC1BEDED07CA4D91AFEB56BD</string>
+ <string>46FAFA88CA3E774263422EB9</string>
+ <string>8915073BE8158EF53FE11B95</string>
+ <string>B90592E4E39AFD1E769F9A95</string>
+ <string>F6383D21195A5BEFC51F6618</string>
+ <string>352B4C7135E3BBBFEBAB7F55</string>
+ <string>E8F0B998CE49FF732F312133</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>C0AC333A6FE8F07600C96890</key>
+ <dict>
+ <key>fileRef</key>
+ <string>1868370C0050315A6B835D42</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>C382F416EFA39BE2CF216044</key>
+ <dict>
+ <key>fileRef</key>
+ <string>5AEFA85A5F1AD206D68B0576</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>C4342DDEEF3C3290956C21DF</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>A8AFEFDF4700447BBCDF9E10</string>
+ <string>0F20828B67FDCB990B1818E9</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>CBA4FEEF7E642535FB39D878</key>
+ <dict>
+ <key>fileRef</key>
+ <string>636AC1003F2C71FFD74542CD</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>CC0A03D531EF0FF199671820</key>
+ <dict>
+ <key>fileRef</key>
+ <string>9CFAC09E370EA1C96C8D2880</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>CC358E38AE146C095C401760</key>
+ <dict>
+ <key>fileRef</key>
+ <string>0260773D27B4AE159FB0B22D</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>D49849E96C0C5FFB93C810CD</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>3133D1CCCF4F1FE3E893509C</string>
+ <string>2FE1D288B8389F925AA3CE0C</string>
+ <string>2663F4401A9075DAC0B24171</string>
+ <string>911BEE248BE640294A081862</string>
+ <string>B034EE43C1EF96D1CBD1328A</string>
+ <string>7FACBF2C8AF0403DD1C11015</string>
+ <string>E232BDE68610C0AC98C0D29F</string>
+ <string>4972C151CE9A8A15BC1AE2C8</string>
+ <string>8A7375A2F98889F35C15E2D7</string>
+ <string>687D79F4C2484F58E9796051</string>
+ <string>42B461F095E85911637DFD60</string>
+ <string>2B05A4C21D00E8CF0DE88447</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Support Files</string>
+ <key>path</key>
+ <string>../examples/Sample/Pods/Target Support Files/Pods-RxLibrary</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>D53A8F2B11E6C2C187AFFF1D</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text</string>
+ <key>path</key>
+ <string>Pods-Sample-acknowledgements.markdown</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>DB007D27F74F8F72C72A1079</key>
+ <dict>
+ <key>containerPortal</key>
+ <string>FBF79DDF04ADEAED54BA2286</string>
+ <key>isa</key>
+ <string>PBXContainerItemProxy</string>
+ <key>proxyType</key>
+ <string>1</string>
+ <key>remoteGlobalIDString</key>
+ <string>6BFD156F312F6CAA1E5B00CA</string>
+ <key>remoteInfo</key>
+ <string>Pods-RxLibrary</string>
+ </dict>
+ <key>DB0257E62EC33F3F316EF017</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>GRXWriter.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>DB3528F609E6177E1C5A691C</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.plist.xml</string>
+ <key>path</key>
+ <string>Pods-SampleTests-acknowledgements.plist</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>DB677464758307786D68CCE9</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>path</key>
+ <string>Pods-SampleTests.release.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>DCAB71BD665AF17533987B69</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>85D5565EC08D14A6A60F1DDA</string>
+ </array>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>DF94410F5DC0A0AB69336DF4</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>archive.ar</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>libPods-Sample.a</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>E14CB6F332A9E58BB5F76C07</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.script.sh</string>
+ <key>path</key>
+ <string>Pods-resources.sh</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>E232BDE68610C0AC98C0D29F</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>name</key>
+ <string>Pods-Sample-RxLibrary-dummy.m</string>
+ <key>path</key>
+ <string>../Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-dummy.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>E86A17CE1D79ECDCEBF91109</key>
+ <dict>
+ <key>fileRef</key>
+ <string>F763F3DF1B47888E75D0ED9C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>E8F0B998CE49FF732F312133</key>
+ <dict>
+ <key>fileRef</key>
+ <string>E232BDE68610C0AC98C0D29F</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>EB29FAB1F81F0D17BDAD72D0</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>GRXWriter+Immediate.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>EF2EE4BC906FF9909348DAB5</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>archive.ar</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>libPods-Sample-RxLibrary.a</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>EF8B807C5A2059D6C709450D</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>Pods-SampleTests-environment.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>F2BB78774BCEFD5DDDF38239</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>69E8FF71552D08D72B9068F1</string>
+ <string>7A8627E1649F66DEE014EB46</string>
+ <string>0D09CEB9308FA5BACEB5F84C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Targets Support Files</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>F2C6AACFE46FFA8DC383DE43</key>
+ <dict>
+ <key>fileRef</key>
+ <string>0D53085043D992DC00E29F0A</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>F6383D21195A5BEFC51F6618</key>
+ <dict>
+ <key>fileRef</key>
+ <string>BDA58E5E1AE450540A2B0227</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>F6C59E5B4CFE053E9F98000E</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>17F4C2F25813E7A4588FF233</string>
+ <key>buildPhases</key>
+ <array>
+ <string>BFE770FF3C0847AB995A82CA</string>
+ <string>1146D04C598DEBA045C96C2F</string>
+ <string>9E8DC61269B141639DA7F859</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>Pods-Sample-RxLibrary</string>
+ <key>productName</key>
+ <string>Pods-Sample-RxLibrary</string>
+ <key>productReference</key>
+ <string>EF2EE4BC906FF9909348DAB5</string>
+ <key>productType</key>
+ <string>com.apple.product-type.library.static</string>
+ </dict>
+ <key>F763F3DF1B47888E75D0ED9C</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>GRXWriter+Transformations.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>F779618174957BE31FCCDE56</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>2B49DCA723ECBC0F2777B960</string>
+ <string>22531AF83592134D3879C3E1</string>
+ <string>0C57EED724EBF58759F9F6DF</string>
+ <string>8CD061F02F905957F4C1D188</string>
+ <string>458FF1EEF4EB9646C699F3DD</string>
+ <string>2B341576464148A01DCFB28B</string>
+ <string>36FF37EAC7E918C4CD867776</string>
+ <string>594F98D43B96AB5C11E61C10</string>
+ <string>B78477CA74AEFC96C25B49B4</string>
+ <string>9CCBE9A628C305B3B089B8DD</string>
+ <string>801BBA7A538CFAE6746966A7</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>F8B4778EF3030EEC2E9927CE</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXTargetDependency</string>
+ <key>name</key>
+ <string>Pods-SampleTests-RxLibrary</string>
+ <key>target</key>
+ <string>3800855A656C8D0813062074</string>
+ <key>targetProxy</key>
+ <string>7DA2A517A18D85B390FB122A</string>
+ </dict>
+ <key>FBF79DDF04ADEAED54BA2286</key>
+ <dict>
+ <key>attributes</key>
+ <dict>
+ <key>LastUpgradeCheck</key>
+ <string>0510</string>
+ </dict>
+ <key>buildConfigurationList</key>
+ <string>3749A34D3DFA6E2F3539E546</string>
+ <key>compatibilityVersion</key>
+ <string>Xcode 3.2</string>
+ <key>developmentRegion</key>
+ <string>English</string>
+ <key>hasScannedForEncodings</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXProject</string>
+ <key>knownRegions</key>
+ <array>
+ <string>en</string>
+ </array>
+ <key>mainGroup</key>
+ <string>397A12919FB4BDD608FE207C</string>
+ <key>productRefGroup</key>
+ <string>8B05D39455D5B23720961FA4</string>
+ <key>projectDirPath</key>
+ <string></string>
+ <key>projectReferences</key>
+ <array/>
+ <key>projectRoot</key>
+ <string></string>
+ <key>targets</key>
+ <array>
+ <string>26E6ACBF137DBC325B4E7DA7</string>
+ <string>6BFD156F312F6CAA1E5B00CA</string>
+ <string>0239F1B46D24E21A8042F47F</string>
+ <string>F6C59E5B4CFE053E9F98000E</string>
+ <string>14D92BB2ED12213381BD2EB9</string>
+ <string>3800855A656C8D0813062074</string>
+ </array>
+ </dict>
+ <key>FC1BEDED07CA4D91AFEB56BD</key>
+ <dict>
+ <key>fileRef</key>
+ <string>57AC9BF19B9635D7476CA5FA</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>FDC6B84EAC9989F0827EA4F3</key>
+ <dict>
+ <key>fileRef</key>
+ <string>0260773D27B4AE159FB0B22D</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>FDC939796E70DC7D141E29FC</key>
+ <dict>
+ <key>fileRef</key>
+ <string>DB0257E62EC33F3F316EF017</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ </dict>
+ <key>rootObject</key>
+ <string>FBF79DDF04ADEAED54BA2286</string>
+</dict>
+</plist>
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-Private.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-Private.xcconfig
new file mode 100644
index 0000000000..5c1a7097be
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-Private.xcconfig
@@ -0,0 +1,5 @@
+#include "Pods-RxLibrary.xcconfig"
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/RxLibrary" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC
+PODS_ROOT = ${SRCROOT} \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-dummy.m b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-dummy.m
new file mode 100644
index 0000000000..79e1460257
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods_RxLibrary : NSObject
+@end
+@implementation PodsDummy_Pods_RxLibrary
+@end
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-prefix.pch b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-prefix.pch
new file mode 100644
index 0000000000..95cf11d9fb
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-prefix.pch
@@ -0,0 +1,5 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#endif
+
+#import "Pods-environment.h"
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary.xcconfig
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary.xcconfig
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-Private.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-Private.xcconfig
new file mode 100644
index 0000000000..2cc81f729d
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-Private.xcconfig
@@ -0,0 +1,5 @@
+#include "Pods-Sample-RxLibrary.xcconfig"
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/RxLibrary" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC
+PODS_ROOT = ${SRCROOT} \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-dummy.m b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-dummy.m
new file mode 100644
index 0000000000..c81b57bbe8
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods_Sample_RxLibrary : NSObject
+@end
+@implementation PodsDummy_Pods_Sample_RxLibrary
+@end
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch
new file mode 100644
index 0000000000..0e807f67a3
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch
@@ -0,0 +1,5 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#endif
+
+#import "Pods-Sample-environment.h"
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary.xcconfig
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary.xcconfig
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.markdown b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.markdown
new file mode 100644
index 0000000000..255149a828
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.markdown
@@ -0,0 +1,3 @@
+# Acknowledgements
+This application makes use of the following third party libraries:
+Generated by CocoaPods - http://cocoapods.org
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.plist b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.plist
new file mode 100644
index 0000000000..e4edebe92d
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.plist
@@ -0,0 +1,29 @@
+<?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>PreferenceSpecifiers</key>
+ <array>
+ <dict>
+ <key>FooterText</key>
+ <string>This application makes use of the following third party libraries:</string>
+ <key>Title</key>
+ <string>Acknowledgements</string>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ </dict>
+ <dict>
+ <key>FooterText</key>
+ <string>Generated by CocoaPods - http://cocoapods.org</string>
+ <key>Title</key>
+ <string></string>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ </dict>
+ </array>
+ <key>StringsTable</key>
+ <string>Acknowledgements</string>
+ <key>Title</key>
+ <string>Acknowledgements</string>
+</dict>
+</plist>
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-dummy.m b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-dummy.m
new file mode 100644
index 0000000000..b5ca68a1c5
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods_Sample : NSObject
+@end
+@implementation PodsDummy_Pods_Sample
+@end
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-environment.h b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-environment.h
new file mode 100644
index 0000000000..b4fd16b369
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-environment.h
@@ -0,0 +1,14 @@
+
+// To check if a library is compiled with CocoaPods you
+// can use the `COCOAPODS` macro definition which is
+// defined in the xcconfigs so it is available in
+// headers also when they are imported in the client
+// project.
+
+
+// RxLibrary
+#define COCOAPODS_POD_AVAILABLE_RxLibrary
+#define COCOAPODS_VERSION_MAJOR_RxLibrary 0
+#define COCOAPODS_VERSION_MINOR_RxLibrary 0
+#define COCOAPODS_VERSION_PATCH_RxLibrary 1
+
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh
new file mode 100755
index 0000000000..e149064a09
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+set -e
+
+mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+
+RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
+> "$RESOURCES_TO_COPY"
+
+install_resource()
+{
+ case $1 in
+ *.storyboard)
+ echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
+ ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
+ ;;
+ *.xib)
+ echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
+ ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
+ ;;
+ *.framework)
+ echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ ;;
+ *.xcdatamodel)
+ echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
+ xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
+ ;;
+ *.xcdatamodeld)
+ echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
+ xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
+ ;;
+ *.xcmappingmodel)
+ echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
+ xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
+ ;;
+ *.xcassets)
+ ;;
+ /*)
+ echo "$1"
+ echo "$1" >> "$RESOURCES_TO_COPY"
+ ;;
+ *)
+ echo "${PODS_ROOT}/$1"
+ echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
+ ;;
+ esac
+}
+
+rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+if [[ "${ACTION}" == "install" ]]; then
+ rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
+rm -f "$RESOURCES_TO_COPY"
+
+if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ]
+then
+ case "${TARGETED_DEVICE_FAMILY}" in
+ 1,2)
+ TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
+ ;;
+ 1)
+ TARGET_DEVICE_ARGS="--target-device iphone"
+ ;;
+ 2)
+ TARGET_DEVICE_ARGS="--target-device ipad"
+ ;;
+ *)
+ TARGET_DEVICE_ARGS="--target-device mac"
+ ;;
+ esac
+ find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig
new file mode 100644
index 0000000000..776727154c
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig
@@ -0,0 +1,6 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC -l"Pods-Sample-RxLibrary"
+OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
+PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig
new file mode 100644
index 0000000000..776727154c
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig
@@ -0,0 +1,6 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC -l"Pods-Sample-RxLibrary"
+OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
+PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-Private.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-Private.xcconfig
new file mode 100644
index 0000000000..a3cd792434
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-Private.xcconfig
@@ -0,0 +1,5 @@
+#include "Pods-SampleTests-RxLibrary.xcconfig"
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/RxLibrary" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC
+PODS_ROOT = ${SRCROOT} \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-dummy.m b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-dummy.m
new file mode 100644
index 0000000000..d57aef11d6
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods_SampleTests_RxLibrary : NSObject
+@end
+@implementation PodsDummy_Pods_SampleTests_RxLibrary
+@end
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch
new file mode 100644
index 0000000000..abd5651587
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch
@@ -0,0 +1,5 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#endif
+
+#import "Pods-SampleTests-environment.h"
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary.xcconfig
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary.xcconfig
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.markdown b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.markdown
new file mode 100644
index 0000000000..255149a828
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.markdown
@@ -0,0 +1,3 @@
+# Acknowledgements
+This application makes use of the following third party libraries:
+Generated by CocoaPods - http://cocoapods.org
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.plist b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.plist
new file mode 100644
index 0000000000..e4edebe92d
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.plist
@@ -0,0 +1,29 @@
+<?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>PreferenceSpecifiers</key>
+ <array>
+ <dict>
+ <key>FooterText</key>
+ <string>This application makes use of the following third party libraries:</string>
+ <key>Title</key>
+ <string>Acknowledgements</string>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ </dict>
+ <dict>
+ <key>FooterText</key>
+ <string>Generated by CocoaPods - http://cocoapods.org</string>
+ <key>Title</key>
+ <string></string>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ </dict>
+ </array>
+ <key>StringsTable</key>
+ <string>Acknowledgements</string>
+ <key>Title</key>
+ <string>Acknowledgements</string>
+</dict>
+</plist>
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-dummy.m b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-dummy.m
new file mode 100644
index 0000000000..01b4ad73ba
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods_SampleTests : NSObject
+@end
+@implementation PodsDummy_Pods_SampleTests
+@end
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-environment.h b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-environment.h
new file mode 100644
index 0000000000..b4fd16b369
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-environment.h
@@ -0,0 +1,14 @@
+
+// To check if a library is compiled with CocoaPods you
+// can use the `COCOAPODS` macro definition which is
+// defined in the xcconfigs so it is available in
+// headers also when they are imported in the client
+// project.
+
+
+// RxLibrary
+#define COCOAPODS_POD_AVAILABLE_RxLibrary
+#define COCOAPODS_VERSION_MAJOR_RxLibrary 0
+#define COCOAPODS_VERSION_MINOR_RxLibrary 0
+#define COCOAPODS_VERSION_PATCH_RxLibrary 1
+
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-resources.sh b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-resources.sh
new file mode 100755
index 0000000000..e149064a09
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-resources.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+set -e
+
+mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+
+RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
+> "$RESOURCES_TO_COPY"
+
+install_resource()
+{
+ case $1 in
+ *.storyboard)
+ echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
+ ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
+ ;;
+ *.xib)
+ echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
+ ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
+ ;;
+ *.framework)
+ echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ ;;
+ *.xcdatamodel)
+ echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
+ xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
+ ;;
+ *.xcdatamodeld)
+ echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
+ xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
+ ;;
+ *.xcmappingmodel)
+ echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
+ xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
+ ;;
+ *.xcassets)
+ ;;
+ /*)
+ echo "$1"
+ echo "$1" >> "$RESOURCES_TO_COPY"
+ ;;
+ *)
+ echo "${PODS_ROOT}/$1"
+ echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
+ ;;
+ esac
+}
+
+rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+if [[ "${ACTION}" == "install" ]]; then
+ rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
+rm -f "$RESOURCES_TO_COPY"
+
+if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ]
+then
+ case "${TARGETED_DEVICE_FAMILY}" in
+ 1,2)
+ TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
+ ;;
+ 1)
+ TARGET_DEVICE_ARGS="--target-device iphone"
+ ;;
+ 2)
+ TARGET_DEVICE_ARGS="--target-device ipad"
+ ;;
+ *)
+ TARGET_DEVICE_ARGS="--target-device mac"
+ ;;
+ esac
+ find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.debug.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.debug.xcconfig
new file mode 100644
index 0000000000..92a3b7d2bd
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.debug.xcconfig
@@ -0,0 +1,6 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC -l"Pods-SampleTests-RxLibrary"
+OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
+PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.release.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.release.xcconfig
new file mode 100644
index 0000000000..92a3b7d2bd
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.release.xcconfig
@@ -0,0 +1,6 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC -l"Pods-SampleTests-RxLibrary"
+OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
+PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown
new file mode 100644
index 0000000000..255149a828
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown
@@ -0,0 +1,3 @@
+# Acknowledgements
+This application makes use of the following third party libraries:
+Generated by CocoaPods - http://cocoapods.org
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.plist b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.plist
new file mode 100644
index 0000000000..e4edebe92d
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.plist
@@ -0,0 +1,29 @@
+<?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>PreferenceSpecifiers</key>
+ <array>
+ <dict>
+ <key>FooterText</key>
+ <string>This application makes use of the following third party libraries:</string>
+ <key>Title</key>
+ <string>Acknowledgements</string>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ </dict>
+ <dict>
+ <key>FooterText</key>
+ <string>Generated by CocoaPods - http://cocoapods.org</string>
+ <key>Title</key>
+ <string></string>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ </dict>
+ </array>
+ <key>StringsTable</key>
+ <string>Acknowledgements</string>
+ <key>Title</key>
+ <string>Acknowledgements</string>
+</dict>
+</plist>
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-dummy.m b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-dummy.m
new file mode 100644
index 0000000000..ade64bd1a9
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods : NSObject
+@end
+@implementation PodsDummy_Pods
+@end
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-environment.h b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-environment.h
new file mode 100644
index 0000000000..b4fd16b369
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-environment.h
@@ -0,0 +1,14 @@
+
+// To check if a library is compiled with CocoaPods you
+// can use the `COCOAPODS` macro definition which is
+// defined in the xcconfigs so it is available in
+// headers also when they are imported in the client
+// project.
+
+
+// RxLibrary
+#define COCOAPODS_POD_AVAILABLE_RxLibrary
+#define COCOAPODS_VERSION_MAJOR_RxLibrary 0
+#define COCOAPODS_VERSION_MINOR_RxLibrary 0
+#define COCOAPODS_VERSION_PATCH_RxLibrary 1
+
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-resources.sh b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-resources.sh
new file mode 100755
index 0000000000..e149064a09
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-resources.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+set -e
+
+mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+
+RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
+> "$RESOURCES_TO_COPY"
+
+install_resource()
+{
+ case $1 in
+ *.storyboard)
+ echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
+ ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
+ ;;
+ *.xib)
+ echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
+ ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
+ ;;
+ *.framework)
+ echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+ ;;
+ *.xcdatamodel)
+ echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
+ xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
+ ;;
+ *.xcdatamodeld)
+ echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
+ xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
+ ;;
+ *.xcmappingmodel)
+ echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
+ xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
+ ;;
+ *.xcassets)
+ ;;
+ /*)
+ echo "$1"
+ echo "$1" >> "$RESOURCES_TO_COPY"
+ ;;
+ *)
+ echo "${PODS_ROOT}/$1"
+ echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
+ ;;
+ esac
+}
+
+rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+if [[ "${ACTION}" == "install" ]]; then
+ rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
+rm -f "$RESOURCES_TO_COPY"
+
+if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ]
+then
+ case "${TARGETED_DEVICE_FAMILY}" in
+ 1,2)
+ TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
+ ;;
+ 1)
+ TARGET_DEVICE_ARGS="--target-device iphone"
+ ;;
+ 2)
+ TARGET_DEVICE_ARGS="--target-device ipad"
+ ;;
+ *)
+ TARGET_DEVICE_ARGS="--target-device mac"
+ ;;
+ esac
+ find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.debug.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.debug.xcconfig
new file mode 100644
index 0000000000..3c7fe4aa00
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.debug.xcconfig
@@ -0,0 +1,6 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC -l"Pods-RxLibrary"
+OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
+PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.release.xcconfig b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.release.xcconfig
new file mode 100644
index 0000000000..3c7fe4aa00
--- /dev/null
+++ b/src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.release.xcconfig
@@ -0,0 +1,6 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
+OTHER_LDFLAGS = -ObjC -l"Pods-RxLibrary"
+OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
+PODS_ROOT = ${SRCROOT}/Pods \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/README.md b/src/objective-c/examples/Sample/README.md
new file mode 100644
index 0000000000..45ba544a34
--- /dev/null
+++ b/src/objective-c/examples/Sample/README.md
@@ -0,0 +1,2 @@
+When contributing changes to this sample, use Cocoapods to manage the workspace
+file and everything under the Pods directory. \ No newline at end of file
diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..142e60e2b2
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
@@ -0,0 +1,955 @@
+<?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>archiveVersion</key>
+ <string>1</string>
+ <key>classes</key>
+ <dict/>
+ <key>objectVersion</key>
+ <string>46</string>
+ <key>objects</key>
+ <dict>
+ <key>04554623324BE4A838846086</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array/>
+ <key>inputPaths</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXShellScriptBuildPhase</string>
+ <key>name</key>
+ <string>Copy Pods Resources</string>
+ <key>outputPaths</key>
+ <array/>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ <key>shellPath</key>
+ <string>/bin/sh</string>
+ <key>shellScript</key>
+ <string>"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh"
+</string>
+ <key>showEnvVarsInLog</key>
+ <string>0</string>
+ </dict>
+ <key>2DC7B7C4C0410F43B9621631</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>archive.ar</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>libPods.a</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>41F7486D8F66994B0BFB84AF</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array/>
+ <key>inputPaths</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXShellScriptBuildPhase</string>
+ <key>name</key>
+ <string>Check Pods Manifest.lock</string>
+ <key>outputPaths</key>
+ <array/>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ <key>shellPath</key>
+ <string>/bin/sh</string>
+ <key>shellScript</key>
+ <string>diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" &gt; /dev/null
+if [[ $? != 0 ]] ; then
+ cat &lt;&lt; EOM
+error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
+EOM
+ exit 1
+fi
+</string>
+ <key>showEnvVarsInLog</key>
+ <string>0</string>
+ </dict>
+ <key>6369A2611A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A26C1A9322E20015FC5C</string>
+ <string>6369A2861A9322E20015FC5C</string>
+ <string>6369A26B1A9322E20015FC5C</string>
+ <string>AB3331C9AE6488E61B2B094E</string>
+ <string>C4C2C5219053E079C9EFB930</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2621A9322E20015FC5C</key>
+ <dict>
+ <key>attributes</key>
+ <dict>
+ <key>LastUpgradeCheck</key>
+ <string>0610</string>
+ <key>ORGANIZATIONNAME</key>
+ <string>gRPC</string>
+ <key>TargetAttributes</key>
+ <dict>
+ <key>6369A2691A9322E20015FC5C</key>
+ <dict>
+ <key>CreatedOnToolsVersion</key>
+ <string>6.1.1</string>
+ </dict>
+ <key>6369A2821A9322E20015FC5C</key>
+ <dict>
+ <key>CreatedOnToolsVersion</key>
+ <string>6.1.1</string>
+ <key>TestTargetID</key>
+ <string>6369A2691A9322E20015FC5C</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>buildConfigurationList</key>
+ <string>6369A2651A9322E20015FC5C</string>
+ <key>compatibilityVersion</key>
+ <string>Xcode 3.2</string>
+ <key>developmentRegion</key>
+ <string>English</string>
+ <key>hasScannedForEncodings</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXProject</string>
+ <key>knownRegions</key>
+ <array>
+ <string>en</string>
+ <string>Base</string>
+ </array>
+ <key>mainGroup</key>
+ <string>6369A2611A9322E20015FC5C</string>
+ <key>productRefGroup</key>
+ <string>6369A26B1A9322E20015FC5C</string>
+ <key>projectDirPath</key>
+ <string></string>
+ <key>projectReferences</key>
+ <array/>
+ <key>projectRoot</key>
+ <string></string>
+ <key>targets</key>
+ <array>
+ <string>6369A2691A9322E20015FC5C</string>
+ <string>6369A2821A9322E20015FC5C</string>
+ </array>
+ </dict>
+ <key>6369A2651A9322E20015FC5C</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>6369A28B1A9322E20015FC5C</string>
+ <string>6369A28C1A9322E20015FC5C</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>defaultConfigurationName</key>
+ <string>Release</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>6369A2661A9322E20015FC5C</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>6369A2761A9322E20015FC5C</string>
+ <string>6369A2731A9322E20015FC5C</string>
+ <string>6369A2701A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>6369A2671A9322E20015FC5C</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>FC81FE63CA655031F3524EC0</string>
+ </array>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>6369A2681A9322E20015FC5C</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>6369A2791A9322E20015FC5C</string>
+ <string>6369A27E1A9322E20015FC5C</string>
+ <string>6369A27B1A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXResourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>6369A2691A9322E20015FC5C</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>6369A28D1A9322E20015FC5C</string>
+ <key>buildPhases</key>
+ <array>
+ <string>41F7486D8F66994B0BFB84AF</string>
+ <string>6369A2661A9322E20015FC5C</string>
+ <string>6369A2671A9322E20015FC5C</string>
+ <string>6369A2681A9322E20015FC5C</string>
+ <string>04554623324BE4A838846086</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>Sample</string>
+ <key>productName</key>
+ <string>Sample</string>
+ <key>productReference</key>
+ <string>6369A26A1A9322E20015FC5C</string>
+ <key>productType</key>
+ <string>com.apple.product-type.application</string>
+ </dict>
+ <key>6369A26A1A9322E20015FC5C</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>wrapper.application</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>Sample.app</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>6369A26B1A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A26A1A9322E20015FC5C</string>
+ <string>6369A2831A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Products</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A26C1A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A2711A9322E20015FC5C</string>
+ <string>6369A2721A9322E20015FC5C</string>
+ <string>6369A2741A9322E20015FC5C</string>
+ <string>6369A2751A9322E20015FC5C</string>
+ <string>6369A2771A9322E20015FC5C</string>
+ <string>6369A27A1A9322E20015FC5C</string>
+ <string>6369A27C1A9322E20015FC5C</string>
+ <string>6369A26D1A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>path</key>
+ <string>Sample</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A26D1A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A26E1A9322E20015FC5C</string>
+ <string>6369A26F1A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Supporting Files</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A26E1A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.plist.xml</string>
+ <key>path</key>
+ <string>Info.plist</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A26F1A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>main.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2701A9322E20015FC5C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>6369A26F1A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6369A2711A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>AppDelegate.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2721A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>AppDelegate.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2731A9322E20015FC5C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>6369A2721A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6369A2741A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.h</string>
+ <key>path</key>
+ <string>ViewController.h</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2751A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>ViewController.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2761A9322E20015FC5C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>6369A2751A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6369A2771A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A2781A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXVariantGroup</string>
+ <key>name</key>
+ <string>Main.storyboard</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2781A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>file.storyboard</string>
+ <key>name</key>
+ <string>Base</string>
+ <key>path</key>
+ <string>Base.lproj/Main.storyboard</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2791A9322E20015FC5C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>6369A2771A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6369A27A1A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>folder.assetcatalog</string>
+ <key>path</key>
+ <string>Images.xcassets</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A27B1A9322E20015FC5C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>6369A27A1A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6369A27C1A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A27D1A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXVariantGroup</string>
+ <key>name</key>
+ <string>LaunchScreen.xib</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A27D1A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>file.xib</string>
+ <key>name</key>
+ <string>Base</string>
+ <key>path</key>
+ <string>Base.lproj/LaunchScreen.xib</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A27E1A9322E20015FC5C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>6369A27C1A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6369A27F1A9322E20015FC5C</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array>
+ <string>6369A28A1A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXSourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>6369A2801A9322E20015FC5C</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXFrameworksBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>6369A2811A9322E20015FC5C</key>
+ <dict>
+ <key>buildActionMask</key>
+ <string>2147483647</string>
+ <key>files</key>
+ <array/>
+ <key>isa</key>
+ <string>PBXResourcesBuildPhase</string>
+ <key>runOnlyForDeploymentPostprocessing</key>
+ <string>0</string>
+ </dict>
+ <key>6369A2821A9322E20015FC5C</key>
+ <dict>
+ <key>buildConfigurationList</key>
+ <string>6369A2901A9322E20015FC5C</string>
+ <key>buildPhases</key>
+ <array>
+ <string>6369A27F1A9322E20015FC5C</string>
+ <string>6369A2801A9322E20015FC5C</string>
+ <string>6369A2811A9322E20015FC5C</string>
+ </array>
+ <key>buildRules</key>
+ <array/>
+ <key>dependencies</key>
+ <array>
+ <string>6369A2851A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXNativeTarget</string>
+ <key>name</key>
+ <string>SampleTests</string>
+ <key>productName</key>
+ <string>SampleTests</string>
+ <key>productReference</key>
+ <string>6369A2831A9322E20015FC5C</string>
+ <key>productType</key>
+ <string>com.apple.product-type.bundle.unit-test</string>
+ </dict>
+ <key>6369A2831A9322E20015FC5C</key>
+ <dict>
+ <key>explicitFileType</key>
+ <string>wrapper.cfbundle</string>
+ <key>includeInIndex</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>path</key>
+ <string>SampleTests.xctest</string>
+ <key>sourceTree</key>
+ <string>BUILT_PRODUCTS_DIR</string>
+ </dict>
+ <key>6369A2841A9322E20015FC5C</key>
+ <dict>
+ <key>containerPortal</key>
+ <string>6369A2621A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXContainerItemProxy</string>
+ <key>proxyType</key>
+ <string>1</string>
+ <key>remoteGlobalIDString</key>
+ <string>6369A2691A9322E20015FC5C</string>
+ <key>remoteInfo</key>
+ <string>Sample</string>
+ </dict>
+ <key>6369A2851A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXTargetDependency</string>
+ <key>target</key>
+ <string>6369A2691A9322E20015FC5C</string>
+ <key>targetProxy</key>
+ <string>6369A2841A9322E20015FC5C</string>
+ </dict>
+ <key>6369A2861A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A2891A9322E20015FC5C</string>
+ <string>6369A2871A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>path</key>
+ <string>SampleTests</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2871A9322E20015FC5C</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>6369A2881A9322E20015FC5C</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Supporting Files</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2881A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.plist.xml</string>
+ <key>path</key>
+ <string>Info.plist</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A2891A9322E20015FC5C</key>
+ <dict>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>sourcecode.c.objc</string>
+ <key>path</key>
+ <string>SampleTests.m</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>6369A28A1A9322E20015FC5C</key>
+ <dict>
+ <key>fileRef</key>
+ <string>6369A2891A9322E20015FC5C</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ <key>6369A28B1A9322E20015FC5C</key>
+ <dict>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>CLANG_CXX_LANGUAGE_STANDARD</key>
+ <string>gnu++0x</string>
+ <key>CLANG_CXX_LIBRARY</key>
+ <string>libc++</string>
+ <key>CLANG_ENABLE_MODULES</key>
+ <string>YES</string>
+ <key>CLANG_ENABLE_OBJC_ARC</key>
+ <string>YES</string>
+ <key>CLANG_WARN_BOOL_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_CONSTANT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_DIRECT_OBJC_ISA_USAGE</key>
+ <string>YES_ERROR</string>
+ <key>CLANG_WARN_EMPTY_BODY</key>
+ <string>YES</string>
+ <key>CLANG_WARN_ENUM_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_INT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_OBJC_ROOT_CLASS</key>
+ <string>YES_ERROR</string>
+ <key>CLANG_WARN_UNREACHABLE_CODE</key>
+ <string>YES</string>
+ <key>CLANG_WARN__DUPLICATE_METHOD_MATCH</key>
+ <string>YES</string>
+ <key>CODE_SIGN_IDENTITY[sdk=iphoneos*]</key>
+ <string>iPhone Developer</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>NO</string>
+ <key>ENABLE_STRICT_OBJC_MSGSEND</key>
+ <string>YES</string>
+ <key>GCC_C_LANGUAGE_STANDARD</key>
+ <string>gnu99</string>
+ <key>GCC_DYNAMIC_NO_PIC</key>
+ <string>NO</string>
+ <key>GCC_OPTIMIZATION_LEVEL</key>
+ <string>0</string>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_SYMBOLS_PRIVATE_EXTERN</key>
+ <string>NO</string>
+ <key>GCC_WARN_64_TO_32_BIT_CONVERSION</key>
+ <string>YES</string>
+ <key>GCC_WARN_ABOUT_RETURN_TYPE</key>
+ <string>YES_ERROR</string>
+ <key>GCC_WARN_UNDECLARED_SELECTOR</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNINITIALIZED_AUTOS</key>
+ <string>YES_AGGRESSIVE</string>
+ <key>GCC_WARN_UNUSED_FUNCTION</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNUSED_VARIABLE</key>
+ <string>YES</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.1</string>
+ <key>MTL_ENABLE_DEBUG_INFO</key>
+ <string>YES</string>
+ <key>ONLY_ACTIVE_ARCH</key>
+ <string>YES</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>TARGETED_DEVICE_FAMILY</key>
+ <string>1,2</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>6369A28C1A9322E20015FC5C</key>
+ <dict>
+ <key>buildSettings</key>
+ <dict>
+ <key>ALWAYS_SEARCH_USER_PATHS</key>
+ <string>NO</string>
+ <key>CLANG_CXX_LANGUAGE_STANDARD</key>
+ <string>gnu++0x</string>
+ <key>CLANG_CXX_LIBRARY</key>
+ <string>libc++</string>
+ <key>CLANG_ENABLE_MODULES</key>
+ <string>YES</string>
+ <key>CLANG_ENABLE_OBJC_ARC</key>
+ <string>YES</string>
+ <key>CLANG_WARN_BOOL_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_CONSTANT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_DIRECT_OBJC_ISA_USAGE</key>
+ <string>YES_ERROR</string>
+ <key>CLANG_WARN_EMPTY_BODY</key>
+ <string>YES</string>
+ <key>CLANG_WARN_ENUM_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_INT_CONVERSION</key>
+ <string>YES</string>
+ <key>CLANG_WARN_OBJC_ROOT_CLASS</key>
+ <string>YES_ERROR</string>
+ <key>CLANG_WARN_UNREACHABLE_CODE</key>
+ <string>YES</string>
+ <key>CLANG_WARN__DUPLICATE_METHOD_MATCH</key>
+ <string>YES</string>
+ <key>CODE_SIGN_IDENTITY[sdk=iphoneos*]</key>
+ <string>iPhone Developer</string>
+ <key>COPY_PHASE_STRIP</key>
+ <string>YES</string>
+ <key>ENABLE_NS_ASSERTIONS</key>
+ <string>NO</string>
+ <key>ENABLE_STRICT_OBJC_MSGSEND</key>
+ <string>YES</string>
+ <key>GCC_C_LANGUAGE_STANDARD</key>
+ <string>gnu99</string>
+ <key>GCC_WARN_64_TO_32_BIT_CONVERSION</key>
+ <string>YES</string>
+ <key>GCC_WARN_ABOUT_RETURN_TYPE</key>
+ <string>YES_ERROR</string>
+ <key>GCC_WARN_UNDECLARED_SELECTOR</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNINITIALIZED_AUTOS</key>
+ <string>YES_AGGRESSIVE</string>
+ <key>GCC_WARN_UNUSED_FUNCTION</key>
+ <string>YES</string>
+ <key>GCC_WARN_UNUSED_VARIABLE</key>
+ <string>YES</string>
+ <key>IPHONEOS_DEPLOYMENT_TARGET</key>
+ <string>8.1</string>
+ <key>MTL_ENABLE_DEBUG_INFO</key>
+ <string>NO</string>
+ <key>SDKROOT</key>
+ <string>iphoneos</string>
+ <key>TARGETED_DEVICE_FAMILY</key>
+ <string>1,2</string>
+ <key>VALIDATE_PRODUCT</key>
+ <string>YES</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>6369A28D1A9322E20015FC5C</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>6369A28E1A9322E20015FC5C</string>
+ <string>6369A28F1A9322E20015FC5C</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>6369A28E1A9322E20015FC5C</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>AC29DD6FCDF962F519FEBB0D</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ASSETCATALOG_COMPILER_APPICON_NAME</key>
+ <string>AppIcon</string>
+ <key>INFOPLIST_FILE</key>
+ <string>Sample/Info.plist</string>
+ <key>LD_RUNPATH_SEARCH_PATHS</key>
+ <string>$(inherited) @executable_path/Frameworks</string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>6369A28F1A9322E20015FC5C</key>
+ <dict>
+ <key>baseConfigurationReference</key>
+ <string>C68330F8D451CC6ACEABA09F</string>
+ <key>buildSettings</key>
+ <dict>
+ <key>ASSETCATALOG_COMPILER_APPICON_NAME</key>
+ <string>AppIcon</string>
+ <key>INFOPLIST_FILE</key>
+ <string>Sample/Info.plist</string>
+ <key>LD_RUNPATH_SEARCH_PATHS</key>
+ <string>$(inherited) @executable_path/Frameworks</string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>6369A2901A9322E20015FC5C</key>
+ <dict>
+ <key>buildConfigurations</key>
+ <array>
+ <string>6369A2911A9322E20015FC5C</string>
+ <string>6369A2921A9322E20015FC5C</string>
+ </array>
+ <key>defaultConfigurationIsVisible</key>
+ <string>0</string>
+ <key>isa</key>
+ <string>XCConfigurationList</string>
+ </dict>
+ <key>6369A2911A9322E20015FC5C</key>
+ <dict>
+ <key>buildSettings</key>
+ <dict>
+ <key>BUNDLE_LOADER</key>
+ <string>$(TEST_HOST)</string>
+ <key>FRAMEWORK_SEARCH_PATHS</key>
+ <array>
+ <string>$(SDKROOT)/Developer/Library/Frameworks</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>GCC_PREPROCESSOR_DEFINITIONS</key>
+ <array>
+ <string>DEBUG=1</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>INFOPLIST_FILE</key>
+ <string>SampleTests/Info.plist</string>
+ <key>LD_RUNPATH_SEARCH_PATHS</key>
+ <string>$(inherited) @executable_path/Frameworks @loader_path/Frameworks</string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>TEST_HOST</key>
+ <string>$(BUILT_PRODUCTS_DIR)/Sample.app/Sample</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Debug</string>
+ </dict>
+ <key>6369A2921A9322E20015FC5C</key>
+ <dict>
+ <key>buildSettings</key>
+ <dict>
+ <key>BUNDLE_LOADER</key>
+ <string>$(TEST_HOST)</string>
+ <key>FRAMEWORK_SEARCH_PATHS</key>
+ <array>
+ <string>$(SDKROOT)/Developer/Library/Frameworks</string>
+ <string>$(inherited)</string>
+ </array>
+ <key>INFOPLIST_FILE</key>
+ <string>SampleTests/Info.plist</string>
+ <key>LD_RUNPATH_SEARCH_PATHS</key>
+ <string>$(inherited) @executable_path/Frameworks @loader_path/Frameworks</string>
+ <key>PRODUCT_NAME</key>
+ <string>$(TARGET_NAME)</string>
+ <key>TEST_HOST</key>
+ <string>$(BUILT_PRODUCTS_DIR)/Sample.app/Sample</string>
+ </dict>
+ <key>isa</key>
+ <string>XCBuildConfiguration</string>
+ <key>name</key>
+ <string>Release</string>
+ </dict>
+ <key>AB3331C9AE6488E61B2B094E</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>AC29DD6FCDF962F519FEBB0D</string>
+ <string>C68330F8D451CC6ACEABA09F</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Pods</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>AC29DD6FCDF962F519FEBB0D</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>name</key>
+ <string>Pods.debug.xcconfig</string>
+ <key>path</key>
+ <string>Pods/Target Support Files/Pods/Pods.debug.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>C4C2C5219053E079C9EFB930</key>
+ <dict>
+ <key>children</key>
+ <array>
+ <string>2DC7B7C4C0410F43B9621631</string>
+ </array>
+ <key>isa</key>
+ <string>PBXGroup</string>
+ <key>name</key>
+ <string>Frameworks</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>C68330F8D451CC6ACEABA09F</key>
+ <dict>
+ <key>includeInIndex</key>
+ <string>1</string>
+ <key>isa</key>
+ <string>PBXFileReference</string>
+ <key>lastKnownFileType</key>
+ <string>text.xcconfig</string>
+ <key>name</key>
+ <string>Pods.release.xcconfig</string>
+ <key>path</key>
+ <string>Pods/Target Support Files/Pods/Pods.release.xcconfig</string>
+ <key>sourceTree</key>
+ <string>&lt;group&gt;</string>
+ </dict>
+ <key>FC81FE63CA655031F3524EC0</key>
+ <dict>
+ <key>fileRef</key>
+ <string>2DC7B7C4C0410F43B9621631</string>
+ <key>isa</key>
+ <string>PBXBuildFile</string>
+ </dict>
+ </dict>
+ <key>rootObject</key>
+ <string>6369A2621A9322E20015FC5C</string>
+</dict>
+</plist>
diff --git a/src/objective-c/examples/Sample/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/src/objective-c/examples/Sample/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..a80c038249
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:Sample.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/src/objective-c/examples/Sample/Sample.xcworkspace/contents.xcworkspacedata b/src/objective-c/examples/Sample/Sample.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..7b5a2f3050
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "group:Sample.xcodeproj">
+ </FileRef>
+ <FileRef
+ location = "group:Pods/Pods.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/src/objective-c/examples/Sample/Sample/AppDelegate.h b/src/objective-c/examples/Sample/Sample/AppDelegate.h
new file mode 100644
index 0000000000..867e62842a
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/AppDelegate.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end
+
diff --git a/src/objective-c/examples/Sample/Sample/AppDelegate.m b/src/objective-c/examples/Sample/Sample/AppDelegate.m
new file mode 100644
index 0000000000..66fceffd85
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/AppDelegate.m
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Override point for customization after application launch.
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // 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.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // 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.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // 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.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // 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.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
diff --git a/src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib b/src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib
new file mode 100644
index 0000000000..c51a8e199e
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207"/>
+ <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
+ </dependencies>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB">
+ <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 gRPC. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
+ <rect key="frame" x="20" y="439" width="441" height="21"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sample" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
+ <rect key="frame" x="20" y="140" width="441" height="43"/>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+ <constraints>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
+ <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
+ <constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
+ <constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
+ <constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
+ </constraints>
+ <nil key="simulatedStatusBarMetrics"/>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <point key="canvasLocation" x="548" y="455"/>
+ </view>
+ </objects>
+</document>
diff --git a/src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard b/src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard
new file mode 100644
index 0000000000..f56d2f3bb5
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/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="" 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/src/objective-c/examples/Sample/Sample/Images.xcassets/AppIcon.appiconset/Contents.json b/src/objective-c/examples/Sample/Sample/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..36d2c80d88
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/Images.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/src/objective-c/examples/Sample/Sample/Info.plist b/src/objective-c/examples/Sample/Sample/Info.plist
new file mode 100644
index 0000000000..ffdc8b3012
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/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>org.grpc.$(PRODUCT_NAME:rfc1034identifier)</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/src/objective-c/examples/Sample/Sample/ViewController.h b/src/objective-c/examples/Sample/Sample/ViewController.h
new file mode 100644
index 0000000000..38cd7f92b6
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/ViewController.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface ViewController : UIViewController
+
+
+@end
+
diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m
new file mode 100644
index 0000000000..70b5d45811
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/ViewController.m
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import "ViewController.h"
+
+@interface ViewController ()
+
+@end
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view, typically from a nib.
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+@end
diff --git a/src/objective-c/examples/Sample/Sample/main.m b/src/objective-c/examples/Sample/Sample/main.m
new file mode 100644
index 0000000000..81e9d44e54
--- /dev/null
+++ b/src/objective-c/examples/Sample/Sample/main.m
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/src/objective-c/examples/Sample/SampleTests/Info.plist b/src/objective-c/examples/Sample/SampleTests/Info.plist
new file mode 100644
index 0000000000..f547b0b707
--- /dev/null
+++ b/src/objective-c/examples/Sample/SampleTests/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>org.grpc.$(PRODUCT_NAME:rfc1034identifier)</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/src/objective-c/examples/Sample/SampleTests/SampleTests.m b/src/objective-c/examples/Sample/SampleTests/SampleTests.m
new file mode 100644
index 0000000000..9a1d4b14d4
--- /dev/null
+++ b/src/objective-c/examples/Sample/SampleTests/SampleTests.m
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+
+@interface SampleTests : XCTestCase
+
+@end
+
+@implementation SampleTests
+
+- (void)setUp {
+ [super setUp];
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+}
+
+- (void)tearDown {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ [super tearDown];
+}
+
+- (void)testExample {
+ // This is an example of a functional test case.
+ XCTAssert(YES, @"Pass");
+}
+
+- (void)testPerformanceExample {
+ // This is an example of a performance test case.
+ [self measureBlock:^{
+ // Put the code you want to measure the time of here.
+ }];
+}
+
+@end
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 178ace6bcf..79ec95dd13 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -349,7 +349,7 @@ endif
.SECONDARY = %.pb.h %.pb.cc
-PROTOC_PLUGINS=\
+PROTOC_PLUGINS =\
% for tgt in targets:
% if tgt.build == 'protoc':
$(BINDIR)/$(CONFIG)/${tgt.name}\
@@ -357,7 +357,7 @@ PROTOC_PLUGINS=\
% endfor
ifeq ($(DEP_MISSING),)
-all: static shared\
+all: static shared plugins\
% for tgt in targets:
% if tgt.build == 'all':
$(BINDIR)/$(CONFIG)/${tgt.name}\
@@ -538,6 +538,8 @@ shared_csharp: shared_c \
grpc_csharp_ext: shared_csharp
+plugins: $(PROTOC_PLUGINS)
+
privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: \
@@ -716,7 +718,7 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc
$(Q) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
-install: install_c install_cxx
+install: install_c install_cxx install-protobuf install-plugins
install_c: install-headers_c install-static_c install-shared_c
@@ -758,9 +760,9 @@ install-static_cxx: static_cxx strip-static_cxx
% endif
% endfor
-install-shared_c: shared_c strip-shared_c
+<%def name="install_shared(lang_filter)">\
% for lib in libs:
-% if lib.language == "c":
+% if lib.language == lang_filter:
% if lib.build == "all":
ifeq ($(SYSTEM),MINGW32)
$(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
@@ -781,56 +783,42 @@ ifneq ($(SYSTEM),Darwin)
$(Q) ldconfig
endif
endif
+</%def>
-install-shared_cxx: shared_cxx strip-shared_cxx
-% for lib in libs:
-% if lib.language == "c++":
-% if lib.build == "all":
-ifeq ($(SYSTEM),MINGW32)
- $(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
- $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
- $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
-else
- $(E) "[INSTALL] Installing lib${lib.name}.$(SHARED_EXT)"
- $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so
-endif
-endif
-% endif
-% endif
-% endfor
+install-shared_c: shared_c strip-shared_c
+${install_shared("c")}
+
+install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c
+${install_shared("c++")}
+
+install-shared_csharp: shared_csharp strip-shared_csharp
+${install_shared("csharp")}
+
+install-protobuf: $(PROTOBUF_DEP)
+ifneq ($(PROTOBUF_DEP),)
+ $(E) "[INSTALL] Installing embedded protobufs"
+ $(Q) $(MAKE) -C third_party/protobuf install prefix=$(prefix)
ifneq ($(SYSTEM),MINGW32)
ifneq ($(SYSTEM),Darwin)
$(Q) ldconfig
endif
endif
+endif
-install-shared_csharp: shared_csharp strip-shared_csharp
-% for lib in libs:
-% if lib.language == "csharp":
-% if lib.build == "all":
+install-plugins: $(PROTOC_PLUGINS)
ifeq ($(SYSTEM),MINGW32)
- $(E) "[INSTALL] Installing ${lib.name}.$(SHARED_EXT)"
- $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
- $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
+ $(Q) false
else
- $(E) "[INSTALL] Installing lib${lib.name}.$(SHARED_EXT)"
- $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so
-endif
-endif
-% endif
+ $(E) "[INSTALL] Installing grpc protoc plugins"
+% for tgt in targets:
+% if tgt.build == 'protoc':
+ $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/${tgt.name} $(prefix)/bin/${tgt.name}
% endif
% endfor
-ifneq ($(SYSTEM),MINGW32)
-ifneq ($(SYSTEM),Darwin)
- $(Q) ldconfig
-endif
endif
clean:
+ $(E) "[CLEAN] Cleaning build directories."
$(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR)
diff --git a/tools/dockerfile/grpc_node/Dockerfile b/tools/dockerfile/grpc_node/Dockerfile
index ce582d2ef1..59aa8cfd1c 100644
--- a/tools/dockerfile/grpc_node/Dockerfile
+++ b/tools/dockerfile/grpc_node/Dockerfile
@@ -11,4 +11,11 @@ RUN make install_c -C /var/local/git/grpc
RUN cd /var/local/git/grpc/src/node && npm install && node-gyp rebuild
+# Add a cacerts directory containing the Google root pem file, allowing the
+# ruby client to access the production test instance
+ADD cacerts cacerts
+
+# Add a service_account directory containing the auth creds file
+ADD service_account service_account
+
CMD ["/usr/bin/nodejs", "/var/local/git/grpc/src/node/interop/interop_server.js", "--use_tls=true", "--port=8040"] \ No newline at end of file
diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh
index 198327feb9..41a1d200e6 100755
--- a/tools/gce_setup/grpc_docker.sh
+++ b/tools/gce_setup/grpc_docker.sh
@@ -1044,11 +1044,39 @@ grpc_interop_gen_php_cmd() {
# cmd=$($grpc_gen_test_cmd $flags)
grpc_interop_gen_node_cmd() {
local cmd_prefix="sudo docker run grpc/node";
- local test_script="/usr/bin/nodejs /var/local/git/grpc/src/node/interop/interop_client.js --use_tls=true";
+ local test_script="/usr/bin/nodejs /var/local/git/grpc/src/node/interop/interop_client.js --use_tls=true --use_test_ca=true";
local the_cmd="$cmd_prefix $test_script $@";
echo $the_cmd
}
+# constructs the full dockerized node gce=>prod interop test cmd.
+#
+# call-seq:
+# flags= .... # generic flags to include the command
+# cmd=$($grpc_gen_test_cmd $flags)
+grpc_cloud_prod_gen_node_cmd() {
+ local cmd_prefix="sudo docker run grpc/node";
+ local test_script="/usr/bin/nodejs /var/local/git/grpc/src/node/interop/interop_client.js --use_tls=true";
+ local gfe_flags=$(_grpc_prod_gfe_flags);
+ local the_cmd="$cmd_prefix $test_script $gfe_flags $@";
+ echo $the_cmd
+}
+
+# constructs the full dockerized node service_account auth interop test cmd.
+#
+# call-seq:
+# flags= .... # generic flags to include the command
+# cmd=$($grpc_gen_test_cmd $flags)
+grpc_cloud_prod_auth_service_account_creds_gen_node_cmd() {
+ local cmd_prefix="sudo docker run grpc/node";
+ local test_script="/usr/bin/nodejs /var/local/git/grpc/src/node/interop/interop_client.js --use_tls=true";
+ local gfe_flags=$(_grpc_prod_gfe_flags);
+ local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem"
+ env_prefix+=" GOOGLE_APPLICATION_CREDENTIALS=/service_account/stubbyCloudTestingTest-7dd63462c60c.json"
+ local the_cmd="$env_prefix $cmd_prefix $test_script $gfe_flags $@";
+ echo $the_cmd
+}
+
# constructs the full dockerized cpp interop test cmd.
#
# call-seq:
diff --git a/tools/gce_setup/shared_startup_funcs.sh b/tools/gce_setup/shared_startup_funcs.sh
index fe00e0c53d..143e039c93 100755
--- a/tools/gce_setup/shared_startup_funcs.sh
+++ b/tools/gce_setup/shared_startup_funcs.sh
@@ -416,6 +416,10 @@ grpc_dockerfile_install() {
grpc_docker_sync_roots_pem $dockerfile_dir/cacerts || return 1;
grpc_docker_sync_service_account $dockerfile_dir/service_account || return 1;
}
+ [[ $image_label == "grpc/node" ]] && {
+ grpc_docker_sync_roots_pem $dockerfile_dir/cacerts || return 1;
+ grpc_docker_sync_service_account $dockerfile_dir/service_account || return 1;
+ }
[[ $image_label == "grpc/cxx" ]] && {
grpc_docker_sync_roots_pem $dockerfile_dir/cacerts || return 1;
grpc_docker_sync_service_account $dockerfile_dir/service_account || return 1;