diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln
new file mode 100644
index 00000000000..5890617acf5
--- /dev/null
+++ b/src/csharp/Grpc.sln
@@ -0,0 +1,38 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcDemo", "GrpcDemo\GrpcDemo.csproj", "{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcApi", "GrpcApi\GrpcApi.csproj", "{7DC1433E-3225-42C7-B7EA-546D56E27A4B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcCore", "GrpcCore\GrpcCore.csproj", "{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcCoreTests", "GrpcCoreTests\GrpcCoreTests.csproj", "{86EC5CB4-4EA2-40A2-8057-86542A0353BB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.ActiveCfg = Debug|x86
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.Build.0 = Debug|x86
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.ActiveCfg = Release|x86
+ {61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.Build.0 = Release|x86
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.Build.0 = Debug|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.ActiveCfg = Release|Any CPU
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.Build.0 = Release|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.Build.0 = Debug|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.ActiveCfg = Release|Any CPU
+ {86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.Build.0 = Release|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.Build.0 = Debug|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.ActiveCfg = Release|Any CPU
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = GrpcDemo\GrpcDemo.csproj
+ EndGlobalSection
+EndGlobal
diff --git a/src/csharp/GrpcApi/.gitignore b/src/csharp/GrpcApi/.gitignore
new file mode 100644
index 00000000000..2cc8cca52d0
--- /dev/null
+++ b/src/csharp/GrpcApi/.gitignore
@@ -0,0 +1,2 @@
+test-results
+bin
diff --git a/src/csharp/GrpcApi/DummyMathServiceClient.cs b/src/csharp/GrpcApi/DummyMathServiceClient.cs
new file mode 100644
index 00000000000..6799109be42
--- /dev/null
+++ b/src/csharp/GrpcApi/DummyMathServiceClient.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Reactive.Linq;
+
+namespace math
+{
+// ///
+// /// Dummy local implementation of math service.
+// ///
+// public class DummyMathServiceClient : IMathServiceClient
+// {
+// public DivReply Div(DivArgs args, CancellationToken token = default(CancellationToken))
+// {
+// // TODO: cancellation...
+// return DivInternal(args);
+// }
+//
+// public Task DivAsync(DivArgs args, CancellationToken token = default(CancellationToken))
+// {
+// return Task.Factory.StartNew(() => DivInternal(args), token);
+// }
+//
+// public IObservable Fib(FibArgs args, CancellationToken token = default(CancellationToken))
+// {
+// if (args.Limit > 0)
+// {
+// // TODO: cancellation
+// return FibInternal(args.Limit).ToObservable();
+// }
+//
+// throw new NotImplementedException("Not implemented yet");
+// }
+//
+// public Task Sum(IObservable inputs, CancellationToken token = default(CancellationToken))
+// {
+// // TODO: implement
+// inputs = null;
+// return Task.Factory.StartNew(() => Num.CreateBuilder().Build(), token);
+// }
+//
+// public IObservable DivMany(IObservable inputs, CancellationToken token = default(CancellationToken))
+// {
+// // TODO: implement
+// inputs = null;
+// return new List { }.ToObservable ();
+// }
+//
+//
+// DivReply DivInternal(DivArgs args)
+// {
+// long quotient = args.Dividend / args.Divisor;
+// long remainder = args.Dividend % args.Divisor;
+// return new DivReply.Builder{ Quotient = quotient, Remainder = remainder }.Build();
+// }
+//
+// IEnumerable FibInternal(long n)
+// {
+// long a = 0;
+// yield return new Num.Builder{Num_=a}.Build();
+//
+// long b = 1;
+// for (long i = 0; i < n - 1; i++)
+// {
+// long temp = a;
+// a = b;
+// b = temp + b;
+// yield return new Num.Builder{Num_=a}.Build();
+// }
+// }
+// }
+}
+
diff --git a/src/csharp/GrpcApi/Examples.cs b/src/csharp/GrpcApi/Examples.cs
new file mode 100644
index 00000000000..d45b702708e
--- /dev/null
+++ b/src/csharp/GrpcApi/Examples.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Reactive.Linq;
+
+namespace math
+{
+ public class Examples
+ {
+ public static void DivExample(IMathServiceClient stub)
+ {
+ DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build());
+ Console.WriteLine("Div Result: " + result);
+ }
+
+ public static void DivAsyncExample(IMathServiceClient stub)
+ {
+ Task call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
+ DivReply result = call.Result;
+ Console.WriteLine(result);
+ }
+
+ public static void DivAsyncWithCancellationExample(IMathServiceClient stub)
+ {
+ Task call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
+ DivReply result = call.Result;
+ Console.WriteLine(result);
+ }
+
+ public static void FibExample(IMathServiceClient stub)
+ {
+ var recorder = new RecordingObserver();
+ stub.Fib(new FibArgs.Builder { Limit = 5 }.Build(), recorder);
+
+ List numbers = recorder.ToList().Result;
+ Console.WriteLine("Fib Result: " + string.Join("|", recorder.ToList().Result));
+ }
+
+ public static void SumExample(IMathServiceClient stub)
+ {
+ List numbers = new List{new Num.Builder { Num_ = 1 }.Build(),
+ new Num.Builder { Num_ = 2 }.Build(),
+ new Num.Builder { Num_ = 3 }.Build()};
+
+ var res = stub.Sum();
+ foreach (var num in numbers) {
+ res.Inputs.OnNext(num);
+ }
+ res.Inputs.OnCompleted();
+
+ Console.WriteLine("Sum Result: " + res.Task.Result);
+ }
+
+ public static void DivManyExample(IMathServiceClient stub)
+ {
+ List divArgsList = new List{
+ new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(),
+ new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(),
+ new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build()
+ };
+
+ var recorder = new RecordingObserver();
+
+ var inputs = stub.DivMany(recorder);
+ foreach (var input in divArgsList)
+ {
+ inputs.OnNext(input);
+ }
+ inputs.OnCompleted();
+
+ Console.WriteLine("DivMany Result: " + string.Join("|", recorder.ToList().Result));
+ }
+
+ public static void DependendRequestsExample(IMathServiceClient stub)
+ {
+ var numberList = new List
+ { new Num.Builder{ Num_ = 1 }.Build(),
+ new Num.Builder{ Num_ = 2 }.Build(), new Num.Builder{ Num_ = 3 }.Build()
+ };
+
+ numberList.ToObservable();
+
+ //IObserver numbers;
+ //Task call = stub.Sum(out numbers);
+ //foreach (var num in numberList)
+ //{
+ // numbers.OnNext(num);
+ //}
+ //numbers.OnCompleted();
+
+ //Num sum = call.Result;
+
+ //DivReply result = stub.Div(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numberList.Count }.Build());
+ }
+ }
+}
+
diff --git a/src/csharp/GrpcApi/GrpcApi.csproj b/src/csharp/GrpcApi/GrpcApi.csproj
new file mode 100644
index 00000000000..d0377828b54
--- /dev/null
+++ b/src/csharp/GrpcApi/GrpcApi.csproj
@@ -0,0 +1,64 @@
+
+
+
+ Debug
+ AnyCPU
+ 10.0.0
+ 2.0
+ {7DC1433E-3225-42C7-B7EA-546D56E27A4B}
+ Library
+ GrpcApi
+ GrpcApi
+ v4.5
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ false
+
+
+ full
+ true
+ bin\Release
+ prompt
+ 4
+ false
+
+
+
+
+ False
+
+
+
+ False
+
+
+ False
+
+
+ ..\lib\Google.ProtocolBuffers.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}
+ GrpcCore
+
+
+
\ No newline at end of file
diff --git a/src/csharp/GrpcApi/IMathServiceClient.cs b/src/csharp/GrpcApi/IMathServiceClient.cs
new file mode 100644
index 00000000000..51385a328f4
--- /dev/null
+++ b/src/csharp/GrpcApi/IMathServiceClient.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Reactive.Linq;
+using Google.GRPC.Core;
+
+namespace math
+{
+ ///
+ /// Hand-written stub for MathService defined in math.proto.
+ /// This code will be generated by gRPC codegen in the future.
+ ///
+ public interface IMathServiceClient
+ {
+ DivReply Div(DivArgs args, CancellationToken token = default(CancellationToken));
+
+ Task DivAsync(DivArgs args, CancellationToken token = default(CancellationToken));
+
+ Task Fib(FibArgs args, IObserver outputs, CancellationToken token = default(CancellationToken));
+
+ ClientStreamingAsyncResult Sum(CancellationToken token = default(CancellationToken));
+
+ IObserver DivMany(IObserver outputs, CancellationToken token = default(CancellationToken));
+ }
+}
\ No newline at end of file
diff --git a/src/csharp/GrpcApi/Math.cs b/src/csharp/GrpcApi/Math.cs
new file mode 100644
index 00000000000..2d700337ac7
--- /dev/null
+++ b/src/csharp/GrpcApi/Math.cs
@@ -0,0 +1,1531 @@
+// Generated by ProtoGen, Version=2.4.1.521, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48. DO NOT EDIT!
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.ProtocolBuffers;
+using pbc = global::Google.ProtocolBuffers.Collections;
+using pbd = global::Google.ProtocolBuffers.Descriptors;
+using scg = global::System.Collections.Generic;
+namespace math {
+
+ namespace Proto {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Math {
+
+ #region Extension registration
+ public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
+ }
+ #endregion
+ #region Static variables
+ internal static pbd::MessageDescriptor internal__static_math_DivArgs__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_math_DivArgs__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_math_DivReply__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_math_DivReply__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_math_FibArgs__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_math_FibArgs__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_math_Num__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_math_Num__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_math_FibReply__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_math_FibReply__FieldAccessorTable;
+ #endregion
+ #region Descriptor
+ public static pbd::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbd::FileDescriptor descriptor;
+
+ static Math() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB",
+ "KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB",
+ "IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB",
+ "IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50",
+ "GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu",
+ "RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E",
+ "aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51",
+ "bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAE="));
+ pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
+ descriptor = root;
+ internal__static_math_DivArgs__Descriptor = Descriptor.MessageTypes[0];
+ internal__static_math_DivArgs__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_math_DivArgs__Descriptor,
+ new string[] { "Dividend", "Divisor", });
+ internal__static_math_DivReply__Descriptor = Descriptor.MessageTypes[1];
+ internal__static_math_DivReply__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_math_DivReply__Descriptor,
+ new string[] { "Quotient", "Remainder", });
+ internal__static_math_FibArgs__Descriptor = Descriptor.MessageTypes[2];
+ internal__static_math_FibArgs__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_math_FibArgs__Descriptor,
+ new string[] { "Limit", });
+ internal__static_math_Num__Descriptor = Descriptor.MessageTypes[3];
+ internal__static_math_Num__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_math_Num__Descriptor,
+ new string[] { "Num_", });
+ internal__static_math_FibReply__Descriptor = Descriptor.MessageTypes[4];
+ internal__static_math_FibReply__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_math_FibReply__Descriptor,
+ new string[] { "Count", });
+ pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
+ RegisterAllExtensions(registry);
+ return registry;
+ };
+ pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbd::FileDescriptor[] {
+ }, assigner);
+ }
+ #endregion
+
+ }
+ }
+ #region Messages
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class DivArgs : pb::GeneratedMessage {
+ private DivArgs() { }
+ private static readonly DivArgs defaultInstance = new DivArgs().MakeReadOnly();
+ private static readonly string[] _divArgsFieldNames = new string[] { "dividend", "divisor" };
+ private static readonly uint[] _divArgsFieldTags = new uint[] { 8, 16 };
+ public static DivArgs DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override DivArgs DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override DivArgs ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::math.Proto.Math.internal__static_math_DivArgs__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {
+ get { return global::math.Proto.Math.internal__static_math_DivArgs__FieldAccessorTable; }
+ }
+
+ public const int DividendFieldNumber = 1;
+ private bool hasDividend;
+ private long dividend_;
+ public bool HasDividend {
+ get { return hasDividend; }
+ }
+ public long Dividend {
+ get { return dividend_; }
+ }
+
+ public const int DivisorFieldNumber = 2;
+ private bool hasDivisor;
+ private long divisor_;
+ public bool HasDivisor {
+ get { return hasDivisor; }
+ }
+ public long Divisor {
+ get { return divisor_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ int size = SerializedSize;
+ string[] field_names = _divArgsFieldNames;
+ if (hasDividend) {
+ output.WriteInt64(1, field_names[0], Dividend);
+ }
+ if (hasDivisor) {
+ output.WriteInt64(2, field_names[1], Divisor);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasDividend) {
+ size += pb::CodedOutputStream.ComputeInt64Size(1, Dividend);
+ }
+ if (hasDivisor) {
+ size += pb::CodedOutputStream.ComputeInt64Size(2, Divisor);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ }
+
+ public static DivArgs ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static DivArgs ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static DivArgs ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static DivArgs ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static DivArgs ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static DivArgs ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static DivArgs ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static DivArgs ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static DivArgs ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static DivArgs ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private DivArgs MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(DivArgs prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(DivArgs cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private DivArgs result;
+
+ private DivArgs PrepareBuilder() {
+ if (resultIsReadOnly) {
+ DivArgs original = result;
+ result = new DivArgs();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override DivArgs MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::math.DivArgs.Descriptor; }
+ }
+
+ public override DivArgs DefaultInstanceForType {
+ get { return global::math.DivArgs.DefaultInstance; }
+ }
+
+ public override DivArgs BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is DivArgs) {
+ return MergeFrom((DivArgs) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(DivArgs other) {
+ if (other == global::math.DivArgs.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasDividend) {
+ Dividend = other.Dividend;
+ }
+ if (other.HasDivisor) {
+ Divisor = other.Divisor;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_divArgsFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _divArgsFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8: {
+ result.hasDividend = input.ReadInt64(ref result.dividend_);
+ break;
+ }
+ case 16: {
+ result.hasDivisor = input.ReadInt64(ref result.divisor_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasDividend {
+ get { return result.hasDividend; }
+ }
+ public long Dividend {
+ get { return result.Dividend; }
+ set { SetDividend(value); }
+ }
+ public Builder SetDividend(long value) {
+ PrepareBuilder();
+ result.hasDividend = true;
+ result.dividend_ = value;
+ return this;
+ }
+ public Builder ClearDividend() {
+ PrepareBuilder();
+ result.hasDividend = false;
+ result.dividend_ = 0L;
+ return this;
+ }
+
+ public bool HasDivisor {
+ get { return result.hasDivisor; }
+ }
+ public long Divisor {
+ get { return result.Divisor; }
+ set { SetDivisor(value); }
+ }
+ public Builder SetDivisor(long value) {
+ PrepareBuilder();
+ result.hasDivisor = true;
+ result.divisor_ = value;
+ return this;
+ }
+ public Builder ClearDivisor() {
+ PrepareBuilder();
+ result.hasDivisor = false;
+ result.divisor_ = 0L;
+ return this;
+ }
+ }
+ static DivArgs() {
+ object.ReferenceEquals(global::math.Proto.Math.Descriptor, null);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class DivReply : pb::GeneratedMessage {
+ private DivReply() { }
+ private static readonly DivReply defaultInstance = new DivReply().MakeReadOnly();
+ private static readonly string[] _divReplyFieldNames = new string[] { "quotient", "remainder" };
+ private static readonly uint[] _divReplyFieldTags = new uint[] { 8, 16 };
+ public static DivReply DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override DivReply DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override DivReply ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::math.Proto.Math.internal__static_math_DivReply__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {
+ get { return global::math.Proto.Math.internal__static_math_DivReply__FieldAccessorTable; }
+ }
+
+ public const int QuotientFieldNumber = 1;
+ private bool hasQuotient;
+ private long quotient_;
+ public bool HasQuotient {
+ get { return hasQuotient; }
+ }
+ public long Quotient {
+ get { return quotient_; }
+ }
+
+ public const int RemainderFieldNumber = 2;
+ private bool hasRemainder;
+ private long remainder_;
+ public bool HasRemainder {
+ get { return hasRemainder; }
+ }
+ public long Remainder {
+ get { return remainder_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ int size = SerializedSize;
+ string[] field_names = _divReplyFieldNames;
+ if (hasQuotient) {
+ output.WriteInt64(1, field_names[0], Quotient);
+ }
+ if (hasRemainder) {
+ output.WriteInt64(2, field_names[1], Remainder);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasQuotient) {
+ size += pb::CodedOutputStream.ComputeInt64Size(1, Quotient);
+ }
+ if (hasRemainder) {
+ size += pb::CodedOutputStream.ComputeInt64Size(2, Remainder);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ }
+
+ public static DivReply ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static DivReply ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static DivReply ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static DivReply ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static DivReply ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static DivReply ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static DivReply ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static DivReply ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static DivReply ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static DivReply ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private DivReply MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(DivReply prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(DivReply cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private DivReply result;
+
+ private DivReply PrepareBuilder() {
+ if (resultIsReadOnly) {
+ DivReply original = result;
+ result = new DivReply();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override DivReply MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::math.DivReply.Descriptor; }
+ }
+
+ public override DivReply DefaultInstanceForType {
+ get { return global::math.DivReply.DefaultInstance; }
+ }
+
+ public override DivReply BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is DivReply) {
+ return MergeFrom((DivReply) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(DivReply other) {
+ if (other == global::math.DivReply.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasQuotient) {
+ Quotient = other.Quotient;
+ }
+ if (other.HasRemainder) {
+ Remainder = other.Remainder;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_divReplyFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _divReplyFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8: {
+ result.hasQuotient = input.ReadInt64(ref result.quotient_);
+ break;
+ }
+ case 16: {
+ result.hasRemainder = input.ReadInt64(ref result.remainder_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasQuotient {
+ get { return result.hasQuotient; }
+ }
+ public long Quotient {
+ get { return result.Quotient; }
+ set { SetQuotient(value); }
+ }
+ public Builder SetQuotient(long value) {
+ PrepareBuilder();
+ result.hasQuotient = true;
+ result.quotient_ = value;
+ return this;
+ }
+ public Builder ClearQuotient() {
+ PrepareBuilder();
+ result.hasQuotient = false;
+ result.quotient_ = 0L;
+ return this;
+ }
+
+ public bool HasRemainder {
+ get { return result.hasRemainder; }
+ }
+ public long Remainder {
+ get { return result.Remainder; }
+ set { SetRemainder(value); }
+ }
+ public Builder SetRemainder(long value) {
+ PrepareBuilder();
+ result.hasRemainder = true;
+ result.remainder_ = value;
+ return this;
+ }
+ public Builder ClearRemainder() {
+ PrepareBuilder();
+ result.hasRemainder = false;
+ result.remainder_ = 0L;
+ return this;
+ }
+ }
+ static DivReply() {
+ object.ReferenceEquals(global::math.Proto.Math.Descriptor, null);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class FibArgs : pb::GeneratedMessage {
+ private FibArgs() { }
+ private static readonly FibArgs defaultInstance = new FibArgs().MakeReadOnly();
+ private static readonly string[] _fibArgsFieldNames = new string[] { "limit" };
+ private static readonly uint[] _fibArgsFieldTags = new uint[] { 8 };
+ public static FibArgs DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override FibArgs DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override FibArgs ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::math.Proto.Math.internal__static_math_FibArgs__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {
+ get { return global::math.Proto.Math.internal__static_math_FibArgs__FieldAccessorTable; }
+ }
+
+ public const int LimitFieldNumber = 1;
+ private bool hasLimit;
+ private long limit_;
+ public bool HasLimit {
+ get { return hasLimit; }
+ }
+ public long Limit {
+ get { return limit_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ int size = SerializedSize;
+ string[] field_names = _fibArgsFieldNames;
+ if (hasLimit) {
+ output.WriteInt64(1, field_names[0], Limit);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasLimit) {
+ size += pb::CodedOutputStream.ComputeInt64Size(1, Limit);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ }
+
+ public static FibArgs ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static FibArgs ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static FibArgs ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static FibArgs ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static FibArgs ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static FibArgs ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static FibArgs ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static FibArgs ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static FibArgs ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static FibArgs ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private FibArgs MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(FibArgs prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(FibArgs cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private FibArgs result;
+
+ private FibArgs PrepareBuilder() {
+ if (resultIsReadOnly) {
+ FibArgs original = result;
+ result = new FibArgs();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override FibArgs MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::math.FibArgs.Descriptor; }
+ }
+
+ public override FibArgs DefaultInstanceForType {
+ get { return global::math.FibArgs.DefaultInstance; }
+ }
+
+ public override FibArgs BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is FibArgs) {
+ return MergeFrom((FibArgs) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(FibArgs other) {
+ if (other == global::math.FibArgs.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasLimit) {
+ Limit = other.Limit;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_fibArgsFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _fibArgsFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8: {
+ result.hasLimit = input.ReadInt64(ref result.limit_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasLimit {
+ get { return result.hasLimit; }
+ }
+ public long Limit {
+ get { return result.Limit; }
+ set { SetLimit(value); }
+ }
+ public Builder SetLimit(long value) {
+ PrepareBuilder();
+ result.hasLimit = true;
+ result.limit_ = value;
+ return this;
+ }
+ public Builder ClearLimit() {
+ PrepareBuilder();
+ result.hasLimit = false;
+ result.limit_ = 0L;
+ return this;
+ }
+ }
+ static FibArgs() {
+ object.ReferenceEquals(global::math.Proto.Math.Descriptor, null);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Num : pb::GeneratedMessage {
+ private Num() { }
+ private static readonly Num defaultInstance = new Num().MakeReadOnly();
+ private static readonly string[] _numFieldNames = new string[] { "num" };
+ private static readonly uint[] _numFieldTags = new uint[] { 8 };
+ public static Num DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override Num DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override Num ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::math.Proto.Math.internal__static_math_Num__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {
+ get { return global::math.Proto.Math.internal__static_math_Num__FieldAccessorTable; }
+ }
+
+ public const int Num_FieldNumber = 1;
+ private bool hasNum_;
+ private long num_;
+ public bool HasNum_ {
+ get { return hasNum_; }
+ }
+ public long Num_ {
+ get { return num_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ int size = SerializedSize;
+ string[] field_names = _numFieldNames;
+ if (hasNum_) {
+ output.WriteInt64(1, field_names[0], Num_);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasNum_) {
+ size += pb::CodedOutputStream.ComputeInt64Size(1, Num_);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ }
+
+ public static Num ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static Num ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static Num ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static Num ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static Num ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static Num ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static Num ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static Num ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static Num ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static Num ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private Num MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(Num prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(Num cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private Num result;
+
+ private Num PrepareBuilder() {
+ if (resultIsReadOnly) {
+ Num original = result;
+ result = new Num();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override Num MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::math.Num.Descriptor; }
+ }
+
+ public override Num DefaultInstanceForType {
+ get { return global::math.Num.DefaultInstance; }
+ }
+
+ public override Num BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is Num) {
+ return MergeFrom((Num) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(Num other) {
+ if (other == global::math.Num.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasNum_) {
+ Num_ = other.Num_;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_numFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _numFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8: {
+ result.hasNum_ = input.ReadInt64(ref result.num_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasNum_ {
+ get { return result.hasNum_; }
+ }
+ public long Num_ {
+ get { return result.Num_; }
+ set { SetNum_(value); }
+ }
+ public Builder SetNum_(long value) {
+ PrepareBuilder();
+ result.hasNum_ = true;
+ result.num_ = value;
+ return this;
+ }
+ public Builder ClearNum_() {
+ PrepareBuilder();
+ result.hasNum_ = false;
+ result.num_ = 0L;
+ return this;
+ }
+ }
+ static Num() {
+ object.ReferenceEquals(global::math.Proto.Math.Descriptor, null);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class FibReply : pb::GeneratedMessage {
+ private FibReply() { }
+ private static readonly FibReply defaultInstance = new FibReply().MakeReadOnly();
+ private static readonly string[] _fibReplyFieldNames = new string[] { "count" };
+ private static readonly uint[] _fibReplyFieldTags = new uint[] { 8 };
+ public static FibReply DefaultInstance {
+ get { return defaultInstance; }
+ }
+
+ public override FibReply DefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ protected override FibReply ThisMessage {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor {
+ get { return global::math.Proto.Math.internal__static_math_FibReply__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {
+ get { return global::math.Proto.Math.internal__static_math_FibReply__FieldAccessorTable; }
+ }
+
+ public const int CountFieldNumber = 1;
+ private bool hasCount;
+ private long count_;
+ public bool HasCount {
+ get { return hasCount; }
+ }
+ public long Count {
+ get { return count_; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return true;
+ }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output) {
+ int size = SerializedSize;
+ string[] field_names = _fibReplyFieldNames;
+ if (hasCount) {
+ output.WriteInt64(1, field_names[0], Count);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize {
+ get {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (hasCount) {
+ size += pb::CodedOutputStream.ComputeInt64Size(1, Count);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ }
+
+ public static FibReply ParseFrom(pb::ByteString data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static FibReply ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static FibReply ParseFrom(byte[] data) {
+ return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static FibReply ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static FibReply ParseFrom(global::System.IO.Stream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static FibReply ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static FibReply ParseDelimitedFrom(global::System.IO.Stream input) {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static FibReply ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static FibReply ParseFrom(pb::ICodedInputStream input) {
+ return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static FibReply ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private FibReply MakeReadOnly() {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(FibReply prototype) {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder {
+ protected override Builder ThisBuilder {
+ get { return this; }
+ }
+ public Builder() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(FibReply cloneFrom) {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private FibReply result;
+
+ private FibReply PrepareBuilder() {
+ if (resultIsReadOnly) {
+ FibReply original = result;
+ result = new FibReply();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized {
+ get { return result.IsInitialized; }
+ }
+
+ protected override FibReply MessageBeingBuilt {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear() {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone() {
+ if (resultIsReadOnly) {
+ return new Builder(result);
+ } else {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType {
+ get { return global::math.FibReply.Descriptor; }
+ }
+
+ public override FibReply DefaultInstanceForType {
+ get { return global::math.FibReply.DefaultInstance; }
+ }
+
+ public override FibReply BuildPartial() {
+ if (resultIsReadOnly) {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other) {
+ if (other is FibReply) {
+ return MergeFrom((FibReply) other);
+ } else {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(FibReply other) {
+ if (other == global::math.FibReply.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.HasCount) {
+ Count = other.Count;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input) {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name)) {
+ if(tag == 0 && field_name != null) {
+ int field_ordinal = global::System.Array.BinarySearch(_fibReplyFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if(field_ordinal >= 0)
+ tag = _fibReplyFieldTags[field_ordinal];
+ else {
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag) {
+ case 0: {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default: {
+ if (pb::WireFormat.IsEndGroupTag(tag)) {
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null) {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8: {
+ result.hasCount = input.ReadInt64(ref result.count_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null) {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public bool HasCount {
+ get { return result.hasCount; }
+ }
+ public long Count {
+ get { return result.Count; }
+ set { SetCount(value); }
+ }
+ public Builder SetCount(long value) {
+ PrepareBuilder();
+ result.hasCount = true;
+ result.count_ = value;
+ return this;
+ }
+ public Builder ClearCount() {
+ PrepareBuilder();
+ result.hasCount = false;
+ result.count_ = 0L;
+ return this;
+ }
+ }
+ static FibReply() {
+ object.ReferenceEquals(global::math.Proto.Math.Descriptor, null);
+ }
+ }
+
+ #endregion
+
+ #region Services
+ /*
+ * Service generation is now disabled by default, use the following option to enable:
+ * option (google.protobuf.csharp_file_options).service_generator_type = GENERIC;
+ */
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/GrpcApi/MathServiceClientStub.cs b/src/csharp/GrpcApi/MathServiceClientStub.cs
new file mode 100644
index 00000000000..493c186b8e5
--- /dev/null
+++ b/src/csharp/GrpcApi/MathServiceClientStub.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Reactive.Linq;
+using Google.GRPC.Core;
+
+namespace math
+{
+ ///
+ /// Implementation of math service stub (this is handwritten version of code
+ /// that will normally be generated).
+ ///
+ public class MathServiceClientStub : IMathServiceClient
+ {
+ readonly Channel channel;
+ readonly TimeSpan methodTimeout;
+
+ public MathServiceClientStub(Channel channel, TimeSpan methodTimeout)
+ {
+ this.channel = channel;
+ this.methodTimeout = methodTimeout;
+ }
+
+ public DivReply Div(DivArgs args, CancellationToken token = default(CancellationToken))
+ {
+ var call = new Google.GRPC.Core.Call("/math.Math/Div", Serialize_DivArgs, Deserialize_DivReply, methodTimeout, channel);
+ return Calls.BlockingUnaryCall(call, args, token);
+ }
+
+ public Task DivAsync(DivArgs args, CancellationToken token = default(CancellationToken))
+ {
+ var call = new Google.GRPC.Core.Call("/math.Math/Div", Serialize_DivArgs, Deserialize_DivReply, methodTimeout, channel);
+ return Calls.AsyncUnaryCall(call, args, token);
+ }
+
+ public Task Fib(FibArgs args, IObserver outputs, CancellationToken token = default(CancellationToken))
+ {
+ var call = new Google.GRPC.Core.Call("/math.Math/Fib", Serialize_FibArgs, Deserialize_Num, methodTimeout, channel);
+ return Calls.AsyncServerStreamingCall(call, args, outputs, token);
+ }
+
+ public ClientStreamingAsyncResult Sum(CancellationToken token = default(CancellationToken))
+ {
+ var call = new Google.GRPC.Core.Call("/math.Math/Sum", Serialize_Num, Deserialize_Num, methodTimeout, channel);
+ return Calls.AsyncClientStreamingCall(call, token);
+ }
+
+ public IObserver DivMany(IObserver outputs, CancellationToken token = default(CancellationToken))
+ {
+ var call = new Google.GRPC.Core.Call("/math.Math/DivMany", Serialize_DivArgs, Deserialize_DivReply, methodTimeout, channel);
+ return Calls.DuplexStreamingCall(call, outputs, token);
+ }
+
+ private static byte[] Serialize_DivArgs(DivArgs arg) {
+ return arg.ToByteArray();
+ }
+
+ private static byte[] Serialize_FibArgs(FibArgs arg) {
+ return arg.ToByteArray();
+ }
+
+ private static byte[] Serialize_Num(Num arg) {
+ return arg.ToByteArray();
+ }
+
+ private static DivReply Deserialize_DivReply(byte[] payload) {
+ return DivReply.CreateBuilder().MergeFrom(payload).Build();
+ }
+
+ private static Num Deserialize_Num(byte[] payload) {
+ return Num.CreateBuilder().MergeFrom(payload).Build();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/csharp/GrpcApi/Messages.cs b/src/csharp/GrpcApi/Messages.cs
new file mode 100644
index 00000000000..b08816bdb7f
--- /dev/null
+++ b/src/csharp/GrpcApi/Messages.cs
@@ -0,0 +1,35 @@
+//using System;
+
+//namespace Google.GRPC.Examples.Math
+//{
+// // Messages in this file are placeholders for actual protobuf message classes
+// // that will be generated from math.proto file.
+//
+// public class DivArgs
+// {
+// public long Dividend{ get; set; }
+// public long Divisor { get; set; }
+// }
+//
+// public class DivReply
+// {
+// public long Quotient { get; set; }
+// public long Remainder { get; set; }
+// }
+//
+// public class FibArgs
+// {
+// public long Limit { get; set; }
+// }
+//
+// public class Number
+// {
+// public long Num { get; set; }
+// }
+//
+// public class FibReply
+// {
+// public long Count { get; set; }
+// }
+//}
+
diff --git a/src/csharp/GrpcApi/Properties/AssemblyInfo.cs b/src/csharp/GrpcApi/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000000..725f12c4860
--- /dev/null
+++ b/src/csharp/GrpcApi/Properties/AssemblyInfo.cs
@@ -0,0 +1,22 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+[assembly: AssemblyTitle ("GrpcApi")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("")]
+[assembly: AssemblyCopyright ("jtattermusch")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+[assembly: AssemblyVersion ("1.0.*")]
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/src/csharp/GrpcApi/RecordingObserver.cs b/src/csharp/GrpcApi/RecordingObserver.cs
new file mode 100644
index 00000000000..8ba3787905a
--- /dev/null
+++ b/src/csharp/GrpcApi/RecordingObserver.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace math
+{
+ public class RecordingObserver : IObserver
+ {
+ TaskCompletionSource> tcs = new TaskCompletionSource>();
+ List data = new List();
+
+ public void OnCompleted()
+ {
+ tcs.SetResult(data);
+ }
+
+ public void OnError(Exception error)
+ {
+ tcs.SetException(error);
+ }
+
+ public void OnNext(T value)
+ {
+ data.Add(value);
+ }
+
+ public Task> ToList() {
+ return tcs.Task;
+ }
+ }
+}
+
diff --git a/src/csharp/GrpcApi/math.proto b/src/csharp/GrpcApi/math.proto
new file mode 100755
index 00000000000..e98b99e002a
--- /dev/null
+++ b/src/csharp/GrpcApi/math.proto
@@ -0,0 +1,50 @@
+syntax = "proto2";
+
+package math;
+
+message DivArgs {
+ optional int64 dividend = 1;
+ optional int64 divisor = 2;
+}
+
+message DivReply {
+ optional int64 quotient = 1;
+ optional int64 remainder = 2;
+}
+
+message FibArgs {
+ optional int64 limit = 1;
+}
+
+message Num {
+ optional int64 num = 1;
+}
+
+message FibReply {
+ optional int64 count = 1;
+}
+
+service Math {
+ // Div divides args.dividend by args.divisor and returns the quotient and
+ // remainder.
+ rpc Div (DivArgs) returns (DivReply) {
+ }
+
+ // DivMany accepts an arbitrary number of division args from the client stream
+ // and sends back the results in the reply stream. The stream continues until
+ // the client closes its end; the server does the same after sending all the
+ // replies. The stream ends immediately if either end aborts.
+ rpc DivMany (stream DivArgs) returns (stream DivReply) {
+ }
+
+ // Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
+ // generates up to limit numbers; otherwise it continues until the call is
+ // canceled. Unlike Fib above, Fib has no final FibReply.
+ rpc Fib (FibArgs) returns (stream Num) {
+ }
+
+ // Sum sums a stream of numbers, returning the final result once the stream
+ // is closed.
+ rpc Sum (stream Num) returns (Num) {
+ }
+}
diff --git a/src/csharp/GrpcCore/.gitignore b/src/csharp/GrpcCore/.gitignore
new file mode 100644
index 00000000000..ba077a4031a
--- /dev/null
+++ b/src/csharp/GrpcCore/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/src/csharp/GrpcCore/Call.cs b/src/csharp/GrpcCore/Call.cs
new file mode 100644
index 00000000000..bf257e5d598
--- /dev/null
+++ b/src/csharp/GrpcCore/Call.cs
@@ -0,0 +1,69 @@
+using System;
+using Google.GRPC.Core.Internal;
+
+namespace Google.GRPC.Core
+{
+ public class Call
+ {
+ readonly string methodName;
+ readonly Func requestSerializer;
+ readonly Func responseDeserializer;
+ readonly TimeSpan timeout;
+ readonly Channel channel;
+
+ // TODO: channel param should be removed in the future.
+ public Call(string methodName,
+ Func requestSerializer,
+ Func responseDeserializer,
+ TimeSpan timeout,
+ Channel channel) {
+ this.methodName = methodName;
+ this.requestSerializer = requestSerializer;
+ this.responseDeserializer = responseDeserializer;
+ this.timeout = timeout;
+ this.channel = channel;
+ }
+
+
+ public Channel Channel
+ {
+ get
+ {
+ return this.channel;
+ }
+ }
+
+ public TimeSpan Timeout
+ {
+ get
+ {
+ return this.timeout;
+ }
+ }
+
+ public string MethodName
+ {
+ get
+ {
+ return this.methodName;
+ }
+ }
+
+ public Func RequestSerializer
+ {
+ get
+ {
+ return this.requestSerializer;
+ }
+ }
+
+ public Func ResponseDeserializer
+ {
+ get
+ {
+ return this.responseDeserializer;
+ }
+ }
+ }
+}
+
diff --git a/src/csharp/GrpcCore/Calls.cs b/src/csharp/GrpcCore/Calls.cs
new file mode 100644
index 00000000000..c3e51cb4781
--- /dev/null
+++ b/src/csharp/GrpcCore/Calls.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.GRPC.Core.Internal;
+
+namespace Google.GRPC.Core
+{
+ // NOTE: this class is work-in-progress
+
+ ///
+ /// Helper methods for generated stubs to make RPC calls.
+ ///
+ public static class Calls
+ {
+ public static TResponse BlockingUnaryCall(Call call, TRequest req, CancellationToken token)
+ {
+ //TODO: implement this in real synchronous style once new GRPC C core API is available.
+ return AsyncUnaryCall(call, req, token).Result;
+ }
+
+ public static async Task AsyncUnaryCall(Call call, TRequest req, CancellationToken token)
+ {
+ var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer);
+ asyncCall.Initialize(call.Channel, call.MethodName);
+ asyncCall.Start(false, GetCompletionQueue());
+
+ await asyncCall.WriteAsync(req);
+ await asyncCall.WritesCompletedAsync();
+
+ TResponse response = await asyncCall.ReadAsync();
+
+ Status status = await asyncCall.Finished;
+
+ if (status.StatusCode != StatusCode.GRPC_STATUS_OK)
+ {
+ throw new RpcException(status);
+ }
+ return response;
+ }
+
+ public static async Task AsyncServerStreamingCall(Call call, TRequest req, IObserver outputs, CancellationToken token)
+ {
+ var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer);
+ asyncCall.Initialize(call.Channel, call.MethodName);
+ asyncCall.Start(false, GetCompletionQueue());
+
+ asyncCall.StartReadingToStream(outputs);
+
+ await asyncCall.WriteAsync(req);
+ await asyncCall.WritesCompletedAsync();
+ }
+
+ public static ClientStreamingAsyncResult AsyncClientStreamingCall(Call call, CancellationToken token)
+ {
+ var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer);
+ asyncCall.Initialize(call.Channel, call.MethodName);
+ asyncCall.Start(false, GetCompletionQueue());
+
+ var task = asyncCall.ReadAsync();
+ var inputs = new StreamingInputObserver(asyncCall);
+ return new ClientStreamingAsyncResult(task, inputs);
+ }
+
+ public static TResponse BlockingClientStreamingCall(Call call, IObservable inputs, CancellationToken token)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static IObserver DuplexStreamingCall(Call call, IObserver outputs, CancellationToken token)
+ {
+ var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer);
+ asyncCall.Initialize(call.Channel, call.MethodName);
+ asyncCall.Start(false, GetCompletionQueue());
+
+ asyncCall.StartReadingToStream(outputs);
+ var inputs = new StreamingInputObserver(asyncCall);
+ return inputs;
+ }
+
+ private static CompletionQueueSafeHandle GetCompletionQueue() {
+ return GrpcEnvironment.ThreadPool.CompletionQueue;
+ }
+ }
+}
+
diff --git a/src/csharp/GrpcCore/Channel.cs b/src/csharp/GrpcCore/Channel.cs
new file mode 100644
index 00000000000..b0d8beeb7bf
--- /dev/null
+++ b/src/csharp/GrpcCore/Channel.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Google.GRPC.Core.Internal;
+
+namespace Google.GRPC.Core
+{
+ public class Channel : IDisposable
+ {
+ ///
+ /// Make sure GPRC environment is initialized before any channels get used.
+ ///
+ static Channel() {
+ GrpcEnvironment.EnsureInitialized();
+ }
+
+ readonly ChannelSafeHandle handle;
+ readonly String target;
+
+ // TODO: add way how to create grpc_secure_channel....
+ // TODO: add support for channel args...
+ public Channel(string target)
+ {
+ this.handle = ChannelSafeHandle.Create(target, IntPtr.Zero);
+ this.target = target;
+ }
+
+ internal ChannelSafeHandle Handle
+ {
+ get
+ {
+ return this.handle;
+ }
+ }
+
+ public string Target
+ {
+ get
+ {
+ return this.target;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (handle != null && !handle.IsInvalid)
+ {
+ handle.Dispose();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/csharp/GrpcCore/ClientStreamingAsyncResult.cs b/src/csharp/GrpcCore/ClientStreamingAsyncResult.cs
new file mode 100644
index 00000000000..9e7312c1fa0
--- /dev/null
+++ b/src/csharp/GrpcCore/ClientStreamingAsyncResult.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Google.GRPC.Core
+{
+ ///
+ /// Return type for client streaming async method.
+ ///
+ public struct ClientStreamingAsyncResult
+ {
+ readonly Task task;
+ readonly IObserver inputs;
+
+ public ClientStreamingAsyncResult(Task task, IObserver inputs)
+ {
+ this.task = task;
+ this.inputs = inputs;
+ }
+
+ public Task Task
+ {
+ get
+ {
+ return this.task;
+ }
+ }
+
+ public IObserver Inputs
+ {
+ get
+ {
+ return this.inputs;
+ }
+ }
+ }
+}
+
diff --git a/src/csharp/GrpcCore/GrpcCore.csproj b/src/csharp/GrpcCore/GrpcCore.csproj
new file mode 100644
index 00000000000..f0c84e78ea6
--- /dev/null
+++ b/src/csharp/GrpcCore/GrpcCore.csproj
@@ -0,0 +1,62 @@
+
+
+
+ Debug
+ AnyCPU
+ 10.0.0
+ 2.0
+ {CCC4440E-49F7-4790-B0AF-FEABB0837AE7}
+ Library
+ GrpcCore
+ GrpcCore
+ v4.5
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ false
+
+
+ full
+ true
+ bin\Release
+ prompt
+ 4
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/csharp/GrpcCore/GrpcEnvironment.cs b/src/csharp/GrpcCore/GrpcEnvironment.cs
new file mode 100644
index 00000000000..7a644f49619
--- /dev/null
+++ b/src/csharp/GrpcCore/GrpcEnvironment.cs
@@ -0,0 +1,91 @@
+using System;
+using Google.GRPC.Core.Internal;
+using System.Runtime.InteropServices;
+
+namespace Google.GRPC.Core
+{
+ ///
+ /// Encapsulates initialization and shutdown of GRPC C core library.
+ /// You should not need to initialize it manually, as static constructors
+ /// should load the library when needed.
+ ///
+ public static class GrpcEnvironment
+ {
+ const int THREAD_POOL_SIZE = 1;
+
+ [DllImport("libgrpc.so")]
+ static extern void grpc_init();
+
+ [DllImport("libgrpc.so")]
+ static extern void grpc_shutdown();
+
+ static object staticLock = new object();
+ static bool initCalled = false;
+ static bool shutdownCalled = false;
+
+ static GrpcThreadPool threadPool = new GrpcThreadPool(THREAD_POOL_SIZE);
+
+ ///
+ /// Makes sure GRPC environment is initialized.
+ ///
+ public static void EnsureInitialized() {
+ lock(staticLock)
+ {
+ if (!initCalled)
+ {
+ initCalled = true;
+ GrpcInit();
+ }
+ }
+ }
+
+ ///
+ /// Shuts down the GRPC environment if it was initialized before.
+ /// Repeated invocations have no effect.
+ ///
+ public static void Shutdown()
+ {
+ lock(staticLock)
+ {
+ if (initCalled && !shutdownCalled)
+ {
+ shutdownCalled = true;
+ GrpcShutdown();
+ }
+ }
+
+ }
+
+ ///
+ /// Initializes GRPC C Core library.
+ ///
+ private static void GrpcInit()
+ {
+ grpc_init();
+ threadPool.Start();
+ // TODO: use proper logging here
+ Console.WriteLine("GRPC initialized.");
+ }
+
+ ///
+ /// Shutdown GRPC C Core library.
+ ///
+ private static void GrpcShutdown()
+ {
+ threadPool.Stop();
+ grpc_shutdown();
+
+ // TODO: use proper logging here
+ Console.WriteLine("GRPC shutdown.");
+ }
+
+ internal static GrpcThreadPool ThreadPool
+ {
+ get
+ {
+ return threadPool;
+ }
+ }
+ }
+}
+
diff --git a/src/csharp/GrpcCore/Internal/AsyncCall.cs b/src/csharp/GrpcCore/Internal/AsyncCall.cs
new file mode 100644
index 00000000000..e83ca0eaa96
--- /dev/null
+++ b/src/csharp/GrpcCore/Internal/AsyncCall.cs
@@ -0,0 +1,485 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Runtime.CompilerServices;
+using Google.GRPC.Core.Internal;
+
+namespace Google.GRPC.Core.Internal
+{
+ ///
+ /// Listener for call events that can be delivered from a completion queue.
+ ///
+ internal interface ICallEventListener {
+
+ void OnClientMetadata();
+
+ void OnRead(byte[] payload);
+
+ void OnWriteAccepted(GRPCOpError error);
+
+ void OnFinishAccepted(GRPCOpError error);
+
+ // ignore the status on server
+ void OnFinished(Status status);
+ }
+
+ ///
+ /// Handle native call lifecycle and provides convenience methods.
+ ///
+ internal class AsyncCall: ICallEventListener, IDisposable
+ {
+ readonly Func serializer;
+ readonly Func deserializer;
+
+ // TODO: make sure the delegate doesn't get garbage collected while
+ // native callbacks are in the completion queue.
+ readonly EventCallbackDelegate callbackHandler;
+
+ object myLock = new object();
+ bool disposed;
+ CallSafeHandle call;
+
+ bool started;
+ bool errorOccured;
+
+ bool cancelRequested;
+ bool halfcloseRequested;
+ bool halfclosed;
+ bool doneWithReading;
+ Nullable finishedStatus;
+
+ TaskCompletionSource