diff --git a/csharp/route_guide/.gitignore b/csharp/route_guide/.gitignore new file mode 100644 index 00000000000..585000ea2d5 --- /dev/null +++ b/csharp/route_guide/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +packages/ +*.suo +*.userprefs diff --git a/csharp/route_guide/README.md b/csharp/route_guide/README.md new file mode 100644 index 00000000000..cdde835dc23 --- /dev/null +++ b/csharp/route_guide/README.md @@ -0,0 +1,392 @@ +#gRPC Basics: C# + +This tutorial provides a basic C# programmer's introduction to working with gRPC. By walking through this example you'll learn how to: + +- Define a service in a .proto file. +- Generate server and client code using the protocol buffer compiler. +- Use the C# gRPC API to write a simple client and server for your service. + +It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial only uses the proto2 version of the protocol buffers language, as proto3 support for C# is not ready yet (see [protobuf C# README](https://github.com/google/protobuf/tree/master/csharp#proto2--proto3)). + +This isn't a comprehensive guide to using gRPC in C#: more reference documentation is coming soon. + +## Why use gRPC? + +Our example is a simple route mapping application that lets clients get information about features on their route, create a summary of their route, and exchange route information such as traffic updates with the server and other clients. + +With gRPC we can define our service once in a .proto file and implement clients and servers in any of gRPC's supported languages, which in turn can be run in environments ranging from servers inside Google to your own tablet - all the complexity of communication between different languages and environments is handled for you by gRPC. We also get all the advantages of working with protocol buffers, including efficient serialization, a simple IDL, and easy interface updating. + +## Example code and setup + +The example code for our tutorial is in [grpc/grpc-common/csharp/route_guide](https://github.com/grpc/grpc-common/tree/master/csharp/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +```shell +$ git clone https://github.com/google/grpc-common.git +``` + +All the files for this tutorial are in the directory `grpc-common/csharp/route_guide`. +Open the solution `grpc-common/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux). + +You also should have the relevant tools installed to generate the server and client interface code. + +**TODO: more on how to install protoc** + +## Defining the service + +Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/csharp/route_guide/RouteGuide/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/sharp/route_guide/RouteGuide/protos/route_guide.proto). + +To define a service, you specify a named `service` in your .proto file: + +```protobuf +service RouteGuide { + ... +} +``` + +Then you define `rpc` methods inside your service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service: + +- A *simple RPC* where the client sends a request to the server using the stub and waits for a response to come back, just like a normal function call. +```protobuf + // Obtains the feature at a given position. + rpc GetFeature(Point) returns (Feature) {} +``` + +- A *server-side streaming RPC* where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. As you can see in our example, you specify a server-side streaming method by placing the `stream` keyword before the *response* type. +```protobuf + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} +``` + +- A *client-side streaming RPC* where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them all and return its response. You specify a server-side streaming method by placing the `stream` keyword before the *request* type. +```protobuf + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} +``` + +- A *bidirectional streaming RPC* where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved. You specify this type of method by placing the `stream` keyword before both the request and the response. +```protobuf + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} +``` + +Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type: +```protobuf +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} +``` + + +## Generating client and server code + +Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C# plugin. + +If you want to run this yourself, make sure you've installed protoc and followed the gRPC C# plugin [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first. + +**TODO: more on how to install protoc and grpc_csharp_plugin** + +Once that's done, the following command can be used to generate the C# code. + +```shell +$ protoc -I RouteGuide/protos --csharp_out=RouteGuide --grpc_out=RouteGuide --plugin=protoc-gen-grpc=`which grpc_csharp_plugin` RouteGuide/protos/route_guide.proto +``` + +**TODO: command for windows** + +Running this command regenerates the following files in the RouteGuide directory: +- `RouteGuide/RouteGuide.cs` defines a namespace `examples` + - This contains all the protocol buffer code to populate, serialize, and retrieve our request and response message types +- `RouteGuide/RouteGuideGrpc.cs`, provides stub and service classes + - an interface `RouteGuide.IRouteGuide` to inherit from when defining RouteGuide service implementations + - a class `RouteGuide.RouteGuideClient` that can be used to access remote RouteGuide instances + + + +## Creating the server + +First let's look at how we create a `RouteGuide` server. If you're only interested in creating gRPC clients, you can skip this section and go straight to [Creating the client](#client) (though you might find it interesting anyway!). + +There are two parts to making our `RouteGuide` service do its job: +- Implementing the service interface generated from our service definition: doing the actual "work" of our service. +- Running a gRPC server to listen for requests from clients and return the service responses. + +You can find our example `RouteGuide` server in [grpc-common/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs](https://github.com/grpc/grpc-common/blob/master/csharp/route_guide/RouteGuideServer/RouteGuideServerImpl.cs). Let's take a closer look at how it works. + +### Implementing RouteGuide + +As you can see, our server has a `RouteGuideImpl` class that implements the generated `RouteGuide.IRouteGuide`: + +```csharp +// RouteGuideImpl provides an implementation of the RouteGuide service. +public class RouteGuideImpl : RouteGuide.IRouteGuide +``` + +`RouteGuideImpl` implements all our service methods. Let's look at the simplest type first, `GetFeature`, which just gets a `Point` from the client and returns the corresponding feature information from its database in a `Feature`. + +```csharp + public Task GetFeature(Grpc.Core.ServerCallContext context, Point request) + { + return Task.FromResult(CheckFeature(request)); + } +``` + +The method is passed a context for the RPC (which is empty in the alpha release), the client's `Point` protocol buffer request, and returns a `Feature` protocol buffer. In the method we create the `Feature` with the appropriate information, and then return it. To allow asynchronous +implementation, the method returns `Task` rather than just `Feature`. You are free to perform your computations synchronously and return +the result once you've finished, just as we do in the example. + +Now let's look at something a bit more complicated - a streaming RPC. `ListFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature` protocol buffers to our client. + +```csharp + // in RouteGuideImpl + public async Task ListFeatures(Grpc.Core.ServerCallContext context, Rectangle request, + Grpc.Core.IServerStreamWriter responseStream) + { + int left = Math.Min(request.Lo.Longitude, request.Hi.Longitude); + int right = Math.Max(request.Lo.Longitude, request.Hi.Longitude); + int top = Math.Max(request.Lo.Latitude, request.Hi.Latitude); + int bottom = Math.Min(request.Lo.Latitude, request.Hi.Latitude); + + foreach (var feature in features) + { + if (!RouteGuideUtil.Exists(feature)) + { + continue; + } + + int lat = feature.Location.Latitude; + int lon = feature.Location.Longitude; + if (lon >= left && lon <= right && lat >= bottom && lat <= top) + { + await responseStream.WriteAsync(feature); + } + } + } +``` + +As you can see, here the request object is a `Rectangle` in which our client wants to find `Feature`s, but instead of returning a simple response we need to write responses to an asynchronous stream `IServerStreamWriter` using async method `WriteAsync`. + +Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumerator](https://github.com/Reactive-Extensions/Rx.NET/blob/master/Ix.NET/Source/System.Interactive.Async/IAsyncEnumerator.cs), to read the stream of requests using async method `MoveNext` and property `Current`. + +```csharp + public async Task RecordRoute(Grpc.Core.ServerCallContext context, + Grpc.Core.IAsyncStreamReader requestStream) + { + int pointCount = 0; + int featureCount = 0; + int distance = 0; + Point previous = null; + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + while (await requestStream.MoveNext()) + { + var point = requestStream.Current; + pointCount++; + if (RouteGuideUtil.Exists(CheckFeature(point))) + { + featureCount++; + } + if (previous != null) + { + distance += (int) CalcDistance(previous, point); + } + previous = point; + } + + stopwatch.Stop(); + return RouteSummary.CreateBuilder().SetPointCount(pointCount) + .SetFeatureCount(featureCount).SetDistance(distance) + .SetElapsedTime((int) (stopwatch.ElapsedMilliseconds / 1000)).Build(); + } +``` +Finally, let's look at our bidirectional streaming RPC `RouteChat`. + +```csharp + public async Task RouteChat(Grpc.Core.ServerCallContext context, + Grpc.Core.IAsyncStreamReader requestStream, Grpc.Core.IServerStreamWriter responseStream) + { + while (await requestStream.MoveNext()) + { + var note = requestStream.Current; + List notes = GetOrCreateNotes(note.Location); + + List prevNotes; + lock (notes) + { + prevNotes = new List(notes); + } + + foreach (var prevNote in prevNotes) + { + await responseStream.WriteAsync(prevNote); + } + + lock (notes) + { + notes.Add(note); + } + } + } +``` + +Here the method receives both `requestStream` and `responseStream` as an argument. Reading the requests is done in a same way as in the `RecordRoute` example. Writing the responses is done the same way as in the `ListFeatures` example. + +### Starting the server + +Once we've implemented all our methods, we also need to start up a gRPC server so that clients can actually use our service. The following snippet shows how we do this for our `RouteGuide` service: + +```csharp +var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile); +GrpcEnvironment.Initialize(); + +Server server = new Server(); +server.AddServiceDefinition(RouteGuide.BindService(new RouteGuideImpl(features))); +int port = server.AddListeningPort("localhost", 50052); +server.Start(); + +Console.WriteLine("RouteGuide server listening on port " + port); +Console.WriteLine("Press any key to stop the server..."); +Console.ReadKey(); + +server.ShutdownAsync().Wait(); +GrpcEnvironment.Shutdown(); +``` +As you can see, we build and start our server using `Grpc.Core.Server` class. To do this, we: + +1. Create an instance of `Grpc.Core.Server`. +1. Create an instance of our service implementation class `RouteGuideImpl`. +3. Register our service implementation with the server using method `AddServiceDefinition` and the generated method `RouteGuide.BindService`. +2. Specify the address and port we want to use to listen for client requests using the `AddListeningPort` method. +4. Call `Start` on the server instance to start an RPC server for our service. + + +## Creating the client + +In this section, we'll look at creating a C# client for our `RouteGuide` service. You can see our complete example client code in [grpc-common/csharp/route_guide/RouteGuideClient/Program.cs](https://github.com/grpc/grpc-common/blob/master/csharp/route_guide/RouteGuideClient/Program.cs). + +### Creating a stub + +To call service methods, we first need to create a *stub*. + +First, we need to create a gRPC client channel that will connect to gRPC server. Then, we use the `RouteGuide.NewStub` method of the `RouteGuide` class generated from our .proto. + +```csharp +GrpcEnvironment.Initialize(); + +using (Channel channel = new Channel("127.0.0.1:50052")) +{ + var client = RouteGuide.NewStub(channel); + + // YOUR CODE GOES HERE +} + +GrpcEnvironment.Shutdown(); +``` + +### Calling service methods + +Now let's look at how we call our service methods. gRPC C# provides asynchronous versions of each of the supported method types. For convenience, +gRPC C# also provides a synchronous method stub, but only for simple (single request/single response) RPCs. + +#### Simple RPC + +Calling the simple RPC `GetFeature` in a synchronous way is nearly as straightforward as calling a local method. + +```csharp +Point request = Point.CreateBuilder().SetLatitude(409146138).SetLongitude(-746188906).Build(); +Feature feature = client.GetFeature(request); +``` + +As you can see, we create and populate a request protocol buffer object (in our case `Point`), and call the desired method on the client object, passing it the request. If the RPC finishes with success, the response protocol buffer (in our case `Feature`) will be returned. Otherwise, an exception of type `RpcException` will be thrown, indicating the status code of the problem. + +Alternatively, if you are in async context, you can call an asynchronous version of the method (and use `await` keyword to await the result): +```csharp +Point request = Point.CreateBuilder().SetLatitude(409146138).SetLongitude(-746188906).Build(); +Feature feature = await client.GetFeatureAsync(request); +``` + +#### Streaming RPCs + +Now let's look at our streaming methods. If you've already read [Creating the server](#server) some of this may look very familiar - streaming RPCs are implemented in a similar way on both sides. The difference with respect to simple call is that the client methods return an instance of a call object, that provides access to request/response streams and/or asynchronous result (depending on the streaming type you are using). + +Here's where we call the server-side streaming method `ListFeatures`, which has property `ReponseStream` of type `IAsyncEnumerator` + +```csharp +using (var call = client.ListFeatures(request)) +{ + while (await call.ResponseStream.MoveNext()) + { + Feature feature = call.ResponseStream.Current; + Console.WriteLine("Received " + feature.ToString()); + } +} +``` + +The client-side streaming method `RecordRoute` is similar, except we use the property `RequestStream` to write the requests one by one using `WriteAsync` and eventually signal that no more request will be send using `CompleteAsync`. The method result can be obtained through the property +`Result`. +```csharp +using (var call = client.RecordRoute()) +{ + foreach (var point in points) + { + await call.RequestStream.WriteAsync(point); + } + await call.RequestStream.CompleteAsync(); + + RouteSummary summary = await call.Result; +} +``` + +Finally, let's look at our bidirectional streaming RPC `RouteChat`. In this case, we write the request to `RequestStream` and receive the responses from `ResponseStream`. As you can see from the example, the streams are independent of each other. + +```csharp + using (var call = client.RouteChat()) + { + var responseReaderTask = Task.Run(async () => + { + while (await call.ResponseStream.MoveNext()) + { + var note = call.ResponseStream.Current; + Console.WriteLine("Received " + note); + } + }); + + foreach (RouteNote request in requests) + { + await call.RequestStream.WriteAsync(request); + } + await call.RequestStream.CompleteAsync(); + await responseReaderTask; +} +``` + +## Try it out! + +Build client and server: + +Open the solution `grpc-common/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux) and hit "Build". + +Run the server, which will listen on port 50052: +``` +> cd RouteGuideServer/bin/Debug +> RouteGuideServer.exe +``` + +Run the client (in a different terminal): +``` +> cd RouteGuideClient/bin/Debug +> RouteGuideClient.exe +``` + +You can also run the server and client directly from Visual Studio. + +On Linux or Mac, use `mono RouteGuideServer.exe` and `mono RouteGuideClient.exe` to run the server and client. \ No newline at end of file diff --git a/csharp/route_guide/RouteGuide.sln b/csharp/route_guide/RouteGuide.sln new file mode 100644 index 00000000000..00065b0ba9d --- /dev/null +++ b/csharp/route_guide/RouteGuide.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuide", "RouteGuide\RouteGuide.csproj", "{49954D9C-5F17-4662-96B2-73BE833DD81A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideClient", "RouteGuideClient\RouteGuideClient.csproj", "{D47BE663-4DE3-4206-B7A8-EA3FA066DADC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideServer", "RouteGuideServer\RouteGuideServer.csproj", "{4B7C7794-BE24-4477-ACE7-18259EB73D27}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {49954D9C-5F17-4662-96B2-73BE833DD81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49954D9C-5F17-4662-96B2-73BE833DD81A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49954D9C-5F17-4662-96B2-73BE833DD81A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49954D9C-5F17-4662-96B2-73BE833DD81A}.Release|Any CPU.Build.0 = Release|Any CPU + {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D47BE663-4DE3-4206-B7A8-EA3FA066DADC}.Release|Any CPU.Build.0 = Release|Any CPU + {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B7C7794-BE24-4477-ACE7-18259EB73D27}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/csharp/route_guide/RouteGuide/Properties/AssemblyInfo.cs b/csharp/route_guide/RouteGuide/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..9c3441e42f4 --- /dev/null +++ b/csharp/route_guide/RouteGuide/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RouteGuide")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RouteGuide")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ef6b85bc-ac27-46de-8714-a658236cc6fb")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/csharp/route_guide/RouteGuide/RouteGuide.cs b/csharp/route_guide/RouteGuide/RouteGuide.cs new file mode 100644 index 00000000000..80508bcd3fd --- /dev/null +++ b/csharp/route_guide/RouteGuide/RouteGuide.cs @@ -0,0 +1,1873 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: route_guide.proto +#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 examples { + + namespace Proto { + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class RouteGuide { + + #region Extension registration + public static void RegisterAllExtensions(pb::ExtensionRegistry registry) { + } + #endregion + #region Static variables + internal static pbd::MessageDescriptor internal__static_examples_Point__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_examples_Point__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_examples_Rectangle__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_examples_Rectangle__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_examples_Feature__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_examples_Feature__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_examples_RouteNote__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_examples_RouteNote__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_examples_RouteSummary__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_examples_RouteSummary__FieldAccessorTable; + #endregion + #region Descriptor + public static pbd::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbd::FileDescriptor descriptor; + + static RouteGuide() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChFyb3V0ZV9ndWlkZS5wcm90bxIIZXhhbXBsZXMiLAoFUG9pbnQSEAoIbGF0", + "aXR1ZGUYASABKAUSEQoJbG9uZ2l0dWRlGAIgASgFIkUKCVJlY3RhbmdsZRIb", + "CgJsbxgBIAEoCzIPLmV4YW1wbGVzLlBvaW50EhsKAmhpGAIgASgLMg8uZXhh", + "bXBsZXMuUG9pbnQiOgoHRmVhdHVyZRIMCgRuYW1lGAEgASgJEiEKCGxvY2F0", + "aW9uGAIgASgLMg8uZXhhbXBsZXMuUG9pbnQiPwoJUm91dGVOb3RlEiEKCGxv", + "Y2F0aW9uGAEgASgLMg8uZXhhbXBsZXMuUG9pbnQSDwoHbWVzc2FnZRgCIAEo", + "CSJiCgxSb3V0ZVN1bW1hcnkSEwoLcG9pbnRfY291bnQYASABKAUSFQoNZmVh", + "dHVyZV9jb3VudBgCIAEoBRIQCghkaXN0YW5jZRgDIAEoBRIUCgxlbGFwc2Vk", + "X3RpbWUYBCABKAUy9QEKClJvdXRlR3VpZGUSMgoKR2V0RmVhdHVyZRIPLmV4", + "YW1wbGVzLlBvaW50GhEuZXhhbXBsZXMuRmVhdHVyZSIAEjoKDExpc3RGZWF0", + "dXJlcxITLmV4YW1wbGVzLlJlY3RhbmdsZRoRLmV4YW1wbGVzLkZlYXR1cmUi", + "ADABEjoKC1JlY29yZFJvdXRlEg8uZXhhbXBsZXMuUG9pbnQaFi5leGFtcGxl", + "cy5Sb3V0ZVN1bW1hcnkiACgBEjsKCVJvdXRlQ2hhdBITLmV4YW1wbGVzLlJv", + "dXRlTm90ZRoTLmV4YW1wbGVzLlJvdXRlTm90ZSIAKAEwAQ==")); + pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { + descriptor = root; + internal__static_examples_Point__Descriptor = Descriptor.MessageTypes[0]; + internal__static_examples_Point__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_examples_Point__Descriptor, + new string[] { "Latitude", "Longitude", }); + internal__static_examples_Rectangle__Descriptor = Descriptor.MessageTypes[1]; + internal__static_examples_Rectangle__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_examples_Rectangle__Descriptor, + new string[] { "Lo", "Hi", }); + internal__static_examples_Feature__Descriptor = Descriptor.MessageTypes[2]; + internal__static_examples_Feature__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_examples_Feature__Descriptor, + new string[] { "Name", "Location", }); + internal__static_examples_RouteNote__Descriptor = Descriptor.MessageTypes[3]; + internal__static_examples_RouteNote__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_examples_RouteNote__Descriptor, + new string[] { "Location", "Message", }); + internal__static_examples_RouteSummary__Descriptor = Descriptor.MessageTypes[4]; + internal__static_examples_RouteSummary__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_examples_RouteSummary__Descriptor, + new string[] { "PointCount", "FeatureCount", "Distance", "ElapsedTime", }); + 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 Point : pb::GeneratedMessage { + private Point() { } + private static readonly Point defaultInstance = new Point().MakeReadOnly(); + private static readonly string[] _pointFieldNames = new string[] { "latitude", "longitude" }; + private static readonly uint[] _pointFieldTags = new uint[] { 8, 16 }; + public static Point DefaultInstance { + get { return defaultInstance; } + } + + public override Point DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override Point ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::examples.Proto.RouteGuide.internal__static_examples_Point__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::examples.Proto.RouteGuide.internal__static_examples_Point__FieldAccessorTable; } + } + + public const int LatitudeFieldNumber = 1; + private bool hasLatitude; + private int latitude_; + public bool HasLatitude { + get { return hasLatitude; } + } + public int Latitude { + get { return latitude_; } + } + + public const int LongitudeFieldNumber = 2; + private bool hasLongitude; + private int longitude_; + public bool HasLongitude { + get { return hasLongitude; } + } + public int Longitude { + get { return longitude_; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _pointFieldNames; + if (hasLatitude) { + output.WriteInt32(1, field_names[0], Latitude); + } + if (hasLongitude) { + output.WriteInt32(2, field_names[1], Longitude); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasLatitude) { + size += pb::CodedOutputStream.ComputeInt32Size(1, Latitude); + } + if (hasLongitude) { + size += pb::CodedOutputStream.ComputeInt32Size(2, Longitude); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static Point ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static Point ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static Point ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static Point ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static Point ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static Point ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Point ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static Point ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static Point ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static Point ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private Point 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(Point 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(Point cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private Point result; + + private Point PrepareBuilder() { + if (resultIsReadOnly) { + Point original = result; + result = new Point(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override Point 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::examples.Point.Descriptor; } + } + + public override Point DefaultInstanceForType { + get { return global::examples.Point.DefaultInstance; } + } + + public override Point BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is Point) { + return MergeFrom((Point) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(Point other) { + if (other == global::examples.Point.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasLatitude) { + Latitude = other.Latitude; + } + if (other.HasLongitude) { + Longitude = other.Longitude; + } + 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(_pointFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _pointFieldTags[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.hasLatitude = input.ReadInt32(ref result.latitude_); + break; + } + case 16: { + result.hasLongitude = input.ReadInt32(ref result.longitude_); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasLatitude { + get { return result.hasLatitude; } + } + public int Latitude { + get { return result.Latitude; } + set { SetLatitude(value); } + } + public Builder SetLatitude(int value) { + PrepareBuilder(); + result.hasLatitude = true; + result.latitude_ = value; + return this; + } + public Builder ClearLatitude() { + PrepareBuilder(); + result.hasLatitude = false; + result.latitude_ = 0; + return this; + } + + public bool HasLongitude { + get { return result.hasLongitude; } + } + public int Longitude { + get { return result.Longitude; } + set { SetLongitude(value); } + } + public Builder SetLongitude(int value) { + PrepareBuilder(); + result.hasLongitude = true; + result.longitude_ = value; + return this; + } + public Builder ClearLongitude() { + PrepareBuilder(); + result.hasLongitude = false; + result.longitude_ = 0; + return this; + } + } + static Point() { + object.ReferenceEquals(global::examples.Proto.RouteGuide.Descriptor, null); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class Rectangle : pb::GeneratedMessage { + private Rectangle() { } + private static readonly Rectangle defaultInstance = new Rectangle().MakeReadOnly(); + private static readonly string[] _rectangleFieldNames = new string[] { "hi", "lo" }; + private static readonly uint[] _rectangleFieldTags = new uint[] { 18, 10 }; + public static Rectangle DefaultInstance { + get { return defaultInstance; } + } + + public override Rectangle DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override Rectangle ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::examples.Proto.RouteGuide.internal__static_examples_Rectangle__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::examples.Proto.RouteGuide.internal__static_examples_Rectangle__FieldAccessorTable; } + } + + public const int LoFieldNumber = 1; + private bool hasLo; + private global::examples.Point lo_; + public bool HasLo { + get { return hasLo; } + } + public global::examples.Point Lo { + get { return lo_ ?? global::examples.Point.DefaultInstance; } + } + + public const int HiFieldNumber = 2; + private bool hasHi; + private global::examples.Point hi_; + public bool HasHi { + get { return hasHi; } + } + public global::examples.Point Hi { + get { return hi_ ?? global::examples.Point.DefaultInstance; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _rectangleFieldNames; + if (hasLo) { + output.WriteMessage(1, field_names[1], Lo); + } + if (hasHi) { + output.WriteMessage(2, field_names[0], Hi); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasLo) { + size += pb::CodedOutputStream.ComputeMessageSize(1, Lo); + } + if (hasHi) { + size += pb::CodedOutputStream.ComputeMessageSize(2, Hi); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static Rectangle ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static Rectangle ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static Rectangle ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static Rectangle ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static Rectangle ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static Rectangle ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Rectangle ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static Rectangle ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static Rectangle ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static Rectangle ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private Rectangle 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(Rectangle 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(Rectangle cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private Rectangle result; + + private Rectangle PrepareBuilder() { + if (resultIsReadOnly) { + Rectangle original = result; + result = new Rectangle(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override Rectangle 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::examples.Rectangle.Descriptor; } + } + + public override Rectangle DefaultInstanceForType { + get { return global::examples.Rectangle.DefaultInstance; } + } + + public override Rectangle BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is Rectangle) { + return MergeFrom((Rectangle) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(Rectangle other) { + if (other == global::examples.Rectangle.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasLo) { + MergeLo(other.Lo); + } + if (other.HasHi) { + MergeHi(other.Hi); + } + 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(_rectangleFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _rectangleFieldTags[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 10: { + global::examples.Point.Builder subBuilder = global::examples.Point.CreateBuilder(); + if (result.hasLo) { + subBuilder.MergeFrom(Lo); + } + input.ReadMessage(subBuilder, extensionRegistry); + Lo = subBuilder.BuildPartial(); + break; + } + case 18: { + global::examples.Point.Builder subBuilder = global::examples.Point.CreateBuilder(); + if (result.hasHi) { + subBuilder.MergeFrom(Hi); + } + input.ReadMessage(subBuilder, extensionRegistry); + Hi = subBuilder.BuildPartial(); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasLo { + get { return result.hasLo; } + } + public global::examples.Point Lo { + get { return result.Lo; } + set { SetLo(value); } + } + public Builder SetLo(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.hasLo = true; + result.lo_ = value; + return this; + } + public Builder SetLo(global::examples.Point.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.hasLo = true; + result.lo_ = builderForValue.Build(); + return this; + } + public Builder MergeLo(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + if (result.hasLo && + result.lo_ != global::examples.Point.DefaultInstance) { + result.lo_ = global::examples.Point.CreateBuilder(result.lo_).MergeFrom(value).BuildPartial(); + } else { + result.lo_ = value; + } + result.hasLo = true; + return this; + } + public Builder ClearLo() { + PrepareBuilder(); + result.hasLo = false; + result.lo_ = null; + return this; + } + + public bool HasHi { + get { return result.hasHi; } + } + public global::examples.Point Hi { + get { return result.Hi; } + set { SetHi(value); } + } + public Builder SetHi(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.hasHi = true; + result.hi_ = value; + return this; + } + public Builder SetHi(global::examples.Point.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.hasHi = true; + result.hi_ = builderForValue.Build(); + return this; + } + public Builder MergeHi(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + if (result.hasHi && + result.hi_ != global::examples.Point.DefaultInstance) { + result.hi_ = global::examples.Point.CreateBuilder(result.hi_).MergeFrom(value).BuildPartial(); + } else { + result.hi_ = value; + } + result.hasHi = true; + return this; + } + public Builder ClearHi() { + PrepareBuilder(); + result.hasHi = false; + result.hi_ = null; + return this; + } + } + static Rectangle() { + object.ReferenceEquals(global::examples.Proto.RouteGuide.Descriptor, null); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class Feature : pb::GeneratedMessage { + private Feature() { } + private static readonly Feature defaultInstance = new Feature().MakeReadOnly(); + private static readonly string[] _featureFieldNames = new string[] { "location", "name" }; + private static readonly uint[] _featureFieldTags = new uint[] { 18, 10 }; + public static Feature DefaultInstance { + get { return defaultInstance; } + } + + public override Feature DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override Feature ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::examples.Proto.RouteGuide.internal__static_examples_Feature__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::examples.Proto.RouteGuide.internal__static_examples_Feature__FieldAccessorTable; } + } + + public const int NameFieldNumber = 1; + private bool hasName; + private string name_ = ""; + public bool HasName { + get { return hasName; } + } + public string Name { + get { return name_; } + } + + public const int LocationFieldNumber = 2; + private bool hasLocation; + private global::examples.Point location_; + public bool HasLocation { + get { return hasLocation; } + } + public global::examples.Point Location { + get { return location_ ?? global::examples.Point.DefaultInstance; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _featureFieldNames; + if (hasName) { + output.WriteString(1, field_names[1], Name); + } + if (hasLocation) { + output.WriteMessage(2, field_names[0], Location); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasName) { + size += pb::CodedOutputStream.ComputeStringSize(1, Name); + } + if (hasLocation) { + size += pb::CodedOutputStream.ComputeMessageSize(2, Location); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static Feature ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static Feature ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static Feature ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static Feature ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static Feature ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static Feature ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static Feature ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static Feature ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static Feature ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static Feature ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private Feature 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(Feature 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(Feature cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private Feature result; + + private Feature PrepareBuilder() { + if (resultIsReadOnly) { + Feature original = result; + result = new Feature(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override Feature 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::examples.Feature.Descriptor; } + } + + public override Feature DefaultInstanceForType { + get { return global::examples.Feature.DefaultInstance; } + } + + public override Feature BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is Feature) { + return MergeFrom((Feature) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(Feature other) { + if (other == global::examples.Feature.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasName) { + Name = other.Name; + } + if (other.HasLocation) { + MergeLocation(other.Location); + } + 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(_featureFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _featureFieldTags[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 10: { + result.hasName = input.ReadString(ref result.name_); + break; + } + case 18: { + global::examples.Point.Builder subBuilder = global::examples.Point.CreateBuilder(); + if (result.hasLocation) { + subBuilder.MergeFrom(Location); + } + input.ReadMessage(subBuilder, extensionRegistry); + Location = subBuilder.BuildPartial(); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasName { + get { return result.hasName; } + } + public string Name { + get { return result.Name; } + set { SetName(value); } + } + public Builder SetName(string value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.hasName = true; + result.name_ = value; + return this; + } + public Builder ClearName() { + PrepareBuilder(); + result.hasName = false; + result.name_ = ""; + return this; + } + + public bool HasLocation { + get { return result.hasLocation; } + } + public global::examples.Point Location { + get { return result.Location; } + set { SetLocation(value); } + } + public Builder SetLocation(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.hasLocation = true; + result.location_ = value; + return this; + } + public Builder SetLocation(global::examples.Point.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.hasLocation = true; + result.location_ = builderForValue.Build(); + return this; + } + public Builder MergeLocation(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + if (result.hasLocation && + result.location_ != global::examples.Point.DefaultInstance) { + result.location_ = global::examples.Point.CreateBuilder(result.location_).MergeFrom(value).BuildPartial(); + } else { + result.location_ = value; + } + result.hasLocation = true; + return this; + } + public Builder ClearLocation() { + PrepareBuilder(); + result.hasLocation = false; + result.location_ = null; + return this; + } + } + static Feature() { + object.ReferenceEquals(global::examples.Proto.RouteGuide.Descriptor, null); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class RouteNote : pb::GeneratedMessage { + private RouteNote() { } + private static readonly RouteNote defaultInstance = new RouteNote().MakeReadOnly(); + private static readonly string[] _routeNoteFieldNames = new string[] { "location", "message" }; + private static readonly uint[] _routeNoteFieldTags = new uint[] { 10, 18 }; + public static RouteNote DefaultInstance { + get { return defaultInstance; } + } + + public override RouteNote DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override RouteNote ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::examples.Proto.RouteGuide.internal__static_examples_RouteNote__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::examples.Proto.RouteGuide.internal__static_examples_RouteNote__FieldAccessorTable; } + } + + public const int LocationFieldNumber = 1; + private bool hasLocation; + private global::examples.Point location_; + public bool HasLocation { + get { return hasLocation; } + } + public global::examples.Point Location { + get { return location_ ?? global::examples.Point.DefaultInstance; } + } + + public const int MessageFieldNumber = 2; + private bool hasMessage; + private string message_ = ""; + public bool HasMessage { + get { return hasMessage; } + } + public string Message { + get { return message_; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _routeNoteFieldNames; + if (hasLocation) { + output.WriteMessage(1, field_names[0], Location); + } + if (hasMessage) { + output.WriteString(2, field_names[1], Message); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasLocation) { + size += pb::CodedOutputStream.ComputeMessageSize(1, Location); + } + if (hasMessage) { + size += pb::CodedOutputStream.ComputeStringSize(2, Message); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static RouteNote ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static RouteNote ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static RouteNote ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static RouteNote ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static RouteNote ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static RouteNote ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static RouteNote ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static RouteNote ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static RouteNote ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static RouteNote ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private RouteNote 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(RouteNote 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(RouteNote cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private RouteNote result; + + private RouteNote PrepareBuilder() { + if (resultIsReadOnly) { + RouteNote original = result; + result = new RouteNote(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override RouteNote 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::examples.RouteNote.Descriptor; } + } + + public override RouteNote DefaultInstanceForType { + get { return global::examples.RouteNote.DefaultInstance; } + } + + public override RouteNote BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is RouteNote) { + return MergeFrom((RouteNote) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(RouteNote other) { + if (other == global::examples.RouteNote.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasLocation) { + MergeLocation(other.Location); + } + if (other.HasMessage) { + Message = other.Message; + } + 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(_routeNoteFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _routeNoteFieldTags[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 10: { + global::examples.Point.Builder subBuilder = global::examples.Point.CreateBuilder(); + if (result.hasLocation) { + subBuilder.MergeFrom(Location); + } + input.ReadMessage(subBuilder, extensionRegistry); + Location = subBuilder.BuildPartial(); + break; + } + case 18: { + result.hasMessage = input.ReadString(ref result.message_); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasLocation { + get { return result.hasLocation; } + } + public global::examples.Point Location { + get { return result.Location; } + set { SetLocation(value); } + } + public Builder SetLocation(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.hasLocation = true; + result.location_ = value; + return this; + } + public Builder SetLocation(global::examples.Point.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.hasLocation = true; + result.location_ = builderForValue.Build(); + return this; + } + public Builder MergeLocation(global::examples.Point value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + if (result.hasLocation && + result.location_ != global::examples.Point.DefaultInstance) { + result.location_ = global::examples.Point.CreateBuilder(result.location_).MergeFrom(value).BuildPartial(); + } else { + result.location_ = value; + } + result.hasLocation = true; + return this; + } + public Builder ClearLocation() { + PrepareBuilder(); + result.hasLocation = false; + result.location_ = null; + return this; + } + + public bool HasMessage { + get { return result.hasMessage; } + } + public string Message { + get { return result.Message; } + set { SetMessage(value); } + } + public Builder SetMessage(string value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.hasMessage = true; + result.message_ = value; + return this; + } + public Builder ClearMessage() { + PrepareBuilder(); + result.hasMessage = false; + result.message_ = ""; + return this; + } + } + static RouteNote() { + object.ReferenceEquals(global::examples.Proto.RouteGuide.Descriptor, null); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class RouteSummary : pb::GeneratedMessage { + private RouteSummary() { } + private static readonly RouteSummary defaultInstance = new RouteSummary().MakeReadOnly(); + private static readonly string[] _routeSummaryFieldNames = new string[] { "distance", "elapsed_time", "feature_count", "point_count" }; + private static readonly uint[] _routeSummaryFieldTags = new uint[] { 24, 32, 16, 8 }; + public static RouteSummary DefaultInstance { + get { return defaultInstance; } + } + + public override RouteSummary DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override RouteSummary ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::examples.Proto.RouteGuide.internal__static_examples_RouteSummary__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::examples.Proto.RouteGuide.internal__static_examples_RouteSummary__FieldAccessorTable; } + } + + public const int PointCountFieldNumber = 1; + private bool hasPointCount; + private int pointCount_; + public bool HasPointCount { + get { return hasPointCount; } + } + public int PointCount { + get { return pointCount_; } + } + + public const int FeatureCountFieldNumber = 2; + private bool hasFeatureCount; + private int featureCount_; + public bool HasFeatureCount { + get { return hasFeatureCount; } + } + public int FeatureCount { + get { return featureCount_; } + } + + public const int DistanceFieldNumber = 3; + private bool hasDistance; + private int distance_; + public bool HasDistance { + get { return hasDistance; } + } + public int Distance { + get { return distance_; } + } + + public const int ElapsedTimeFieldNumber = 4; + private bool hasElapsedTime; + private int elapsedTime_; + public bool HasElapsedTime { + get { return hasElapsedTime; } + } + public int ElapsedTime { + get { return elapsedTime_; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _routeSummaryFieldNames; + if (hasPointCount) { + output.WriteInt32(1, field_names[3], PointCount); + } + if (hasFeatureCount) { + output.WriteInt32(2, field_names[2], FeatureCount); + } + if (hasDistance) { + output.WriteInt32(3, field_names[0], Distance); + } + if (hasElapsedTime) { + output.WriteInt32(4, field_names[1], ElapsedTime); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasPointCount) { + size += pb::CodedOutputStream.ComputeInt32Size(1, PointCount); + } + if (hasFeatureCount) { + size += pb::CodedOutputStream.ComputeInt32Size(2, FeatureCount); + } + if (hasDistance) { + size += pb::CodedOutputStream.ComputeInt32Size(3, Distance); + } + if (hasElapsedTime) { + size += pb::CodedOutputStream.ComputeInt32Size(4, ElapsedTime); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static RouteSummary ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static RouteSummary ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static RouteSummary ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static RouteSummary ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static RouteSummary ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static RouteSummary ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static RouteSummary ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static RouteSummary ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static RouteSummary ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static RouteSummary ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private RouteSummary 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(RouteSummary 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(RouteSummary cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private RouteSummary result; + + private RouteSummary PrepareBuilder() { + if (resultIsReadOnly) { + RouteSummary original = result; + result = new RouteSummary(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override RouteSummary 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::examples.RouteSummary.Descriptor; } + } + + public override RouteSummary DefaultInstanceForType { + get { return global::examples.RouteSummary.DefaultInstance; } + } + + public override RouteSummary BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is RouteSummary) { + return MergeFrom((RouteSummary) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(RouteSummary other) { + if (other == global::examples.RouteSummary.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasPointCount) { + PointCount = other.PointCount; + } + if (other.HasFeatureCount) { + FeatureCount = other.FeatureCount; + } + if (other.HasDistance) { + Distance = other.Distance; + } + if (other.HasElapsedTime) { + ElapsedTime = other.ElapsedTime; + } + 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(_routeSummaryFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _routeSummaryFieldTags[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.hasPointCount = input.ReadInt32(ref result.pointCount_); + break; + } + case 16: { + result.hasFeatureCount = input.ReadInt32(ref result.featureCount_); + break; + } + case 24: { + result.hasDistance = input.ReadInt32(ref result.distance_); + break; + } + case 32: { + result.hasElapsedTime = input.ReadInt32(ref result.elapsedTime_); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasPointCount { + get { return result.hasPointCount; } + } + public int PointCount { + get { return result.PointCount; } + set { SetPointCount(value); } + } + public Builder SetPointCount(int value) { + PrepareBuilder(); + result.hasPointCount = true; + result.pointCount_ = value; + return this; + } + public Builder ClearPointCount() { + PrepareBuilder(); + result.hasPointCount = false; + result.pointCount_ = 0; + return this; + } + + public bool HasFeatureCount { + get { return result.hasFeatureCount; } + } + public int FeatureCount { + get { return result.FeatureCount; } + set { SetFeatureCount(value); } + } + public Builder SetFeatureCount(int value) { + PrepareBuilder(); + result.hasFeatureCount = true; + result.featureCount_ = value; + return this; + } + public Builder ClearFeatureCount() { + PrepareBuilder(); + result.hasFeatureCount = false; + result.featureCount_ = 0; + return this; + } + + public bool HasDistance { + get { return result.hasDistance; } + } + public int Distance { + get { return result.Distance; } + set { SetDistance(value); } + } + public Builder SetDistance(int value) { + PrepareBuilder(); + result.hasDistance = true; + result.distance_ = value; + return this; + } + public Builder ClearDistance() { + PrepareBuilder(); + result.hasDistance = false; + result.distance_ = 0; + return this; + } + + public bool HasElapsedTime { + get { return result.hasElapsedTime; } + } + public int ElapsedTime { + get { return result.ElapsedTime; } + set { SetElapsedTime(value); } + } + public Builder SetElapsedTime(int value) { + PrepareBuilder(); + result.hasElapsedTime = true; + result.elapsedTime_ = value; + return this; + } + public Builder ClearElapsedTime() { + PrepareBuilder(); + result.hasElapsedTime = false; + result.elapsedTime_ = 0; + return this; + } + } + static RouteSummary() { + object.ReferenceEquals(global::examples.Proto.RouteGuide.Descriptor, null); + } + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/route_guide/RouteGuide/RouteGuide.csproj b/csharp/route_guide/RouteGuide/RouteGuide.csproj new file mode 100644 index 00000000000..9b5daa6e4bc --- /dev/null +++ b/csharp/route_guide/RouteGuide/RouteGuide.csproj @@ -0,0 +1,99 @@ + + + + + + + + Debug + AnyCPU + {49954D9C-5F17-4662-96B2-73BE833DD81A} + Library + Properties + RouteGuide + RouteGuide + v4.5 + 512 + 247686dc + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll + + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll + + + ..\packages\Grpc.Core.0.5.0\lib\net45\Grpc.Core.dll + + + False + ..\packages\Newtonsoft.Json.7.0.1-beta2\lib\net45\Newtonsoft.Json.dll + + + + ..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + + + ..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + \ No newline at end of file diff --git a/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs b/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs new file mode 100644 index 00000000000..c4b3900dca3 --- /dev/null +++ b/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs @@ -0,0 +1,123 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: route_guide.proto +#region Designer generated code + +using System; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; + +namespace examples { + public static class RouteGuide + { + static readonly string __ServiceName = "examples.RouteGuide"; + + static readonly Marshaller __Marshaller_Point = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.Point.ParseFrom); + static readonly Marshaller __Marshaller_Feature = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.Feature.ParseFrom); + static readonly Marshaller __Marshaller_Rectangle = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.Rectangle.ParseFrom); + static readonly Marshaller __Marshaller_RouteSummary = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.RouteSummary.ParseFrom); + static readonly Marshaller __Marshaller_RouteNote = Marshallers.Create((arg) => arg.ToByteArray(), global::examples.RouteNote.ParseFrom); + + static readonly Method __Method_GetFeature = new Method( + MethodType.Unary, + "GetFeature", + __Marshaller_Point, + __Marshaller_Feature); + + static readonly Method __Method_ListFeatures = new Method( + MethodType.ServerStreaming, + "ListFeatures", + __Marshaller_Rectangle, + __Marshaller_Feature); + + static readonly Method __Method_RecordRoute = new Method( + MethodType.ClientStreaming, + "RecordRoute", + __Marshaller_Point, + __Marshaller_RouteSummary); + + static readonly Method __Method_RouteChat = new Method( + MethodType.DuplexStreaming, + "RouteChat", + __Marshaller_RouteNote, + __Marshaller_RouteNote); + + // client-side stub interface + public interface IRouteGuideClient + { + global::examples.Feature GetFeature(global::examples.Point request, CancellationToken token = default(CancellationToken)); + Task GetFeatureAsync(global::examples.Point request, CancellationToken token = default(CancellationToken)); + AsyncServerStreamingCall ListFeatures(global::examples.Rectangle request, CancellationToken token = default(CancellationToken)); + AsyncClientStreamingCall RecordRoute(CancellationToken token = default(CancellationToken)); + AsyncDuplexStreamingCall RouteChat(CancellationToken token = default(CancellationToken)); + } + + // server-side interface + public interface IRouteGuide + { + Task GetFeature(ServerCallContext context, global::examples.Point request); + Task ListFeatures(ServerCallContext context, global::examples.Rectangle request, IServerStreamWriter responseStream); + Task RecordRoute(ServerCallContext context, IAsyncStreamReader requestStream); + Task RouteChat(ServerCallContext context, IAsyncStreamReader requestStream, IServerStreamWriter responseStream); + } + + // client stub + public class RouteGuideClient : AbstractStub, IRouteGuideClient + { + public RouteGuideClient(Channel channel) : this(channel, StubConfiguration.Default) + { + } + public RouteGuideClient(Channel channel, StubConfiguration config) : base(channel, config) + { + } + public global::examples.Feature GetFeature(global::examples.Point request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_GetFeature); + return Calls.BlockingUnaryCall(call, request, token); + } + public Task GetFeatureAsync(global::examples.Point request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_GetFeature); + return Calls.AsyncUnaryCall(call, request, token); + } + public AsyncServerStreamingCall ListFeatures(global::examples.Rectangle request, CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_ListFeatures); + return Calls.AsyncServerStreamingCall(call, request, token); + } + public AsyncClientStreamingCall RecordRoute(CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_RecordRoute); + return Calls.AsyncClientStreamingCall(call, token); + } + public AsyncDuplexStreamingCall RouteChat(CancellationToken token = default(CancellationToken)) + { + var call = CreateCall(__ServiceName, __Method_RouteChat); + return Calls.AsyncDuplexStreamingCall(call, token); + } + } + + // creates service definition that can be registered with a server + public static ServerServiceDefinition BindService(IRouteGuide serviceImpl) + { + return ServerServiceDefinition.CreateBuilder(__ServiceName) + .AddMethod(__Method_GetFeature, serviceImpl.GetFeature) + .AddMethod(__Method_ListFeatures, serviceImpl.ListFeatures) + .AddMethod(__Method_RecordRoute, serviceImpl.RecordRoute) + .AddMethod(__Method_RouteChat, serviceImpl.RouteChat).Build(); + } + + // creates a new client stub + public static IRouteGuideClient NewStub(Channel channel) + { + return new RouteGuideClient(channel); + } + + // creates a new client stub + public static IRouteGuideClient NewStub(Channel channel, StubConfiguration config) + { + return new RouteGuideClient(channel, config); + } + } +} +#endregion diff --git a/csharp/route_guide/RouteGuide/RouteGuideUtil.cs b/csharp/route_guide/RouteGuide/RouteGuideUtil.cs new file mode 100644 index 00000000000..6fb8b1e28ab --- /dev/null +++ b/csharp/route_guide/RouteGuide/RouteGuideUtil.cs @@ -0,0 +1,67 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace examples +{ + public static class RouteGuideUtil + { + public const string DefaultFeaturesFile = "route_guide_db.json"; + + private const double CoordFactor = 1e7; + + /// + /// Indicates whether the given feature exists (i.e. has a valid name). + /// + public static bool Exists(Feature feature) + { + return feature != null && (feature.Name.Length != 0); + } + + public static double GetLatitude(Point point) + { + return point.Latitude / CoordFactor; + } + + public static double GetLongitude(Point point) + { + return point.Longitude / CoordFactor; + } + + /// + /// Parses features from a JSON file. + /// + public static List ParseFeatures(string filename) + { + var features = new List(); + var jsonFeatures = JsonConvert.DeserializeObject>(File.ReadAllText(filename)); + + + foreach(var jsonFeature in jsonFeatures) + { + features.Add(Feature.CreateBuilder().SetName(jsonFeature.name).SetLocation( + Point.CreateBuilder() + .SetLongitude(jsonFeature.location.longitude) + .SetLatitude(jsonFeature.location.latitude).Build()).Build()); + } + return features; + } + + private class JsonFeature + { + public string name; + public JsonLocation location; + } + + private class JsonLocation + { + public int longitude; + public int latitude; + } + } +} diff --git a/csharp/route_guide/RouteGuide/packages.config b/csharp/route_guide/RouteGuide/packages.config new file mode 100644 index 00000000000..b3efb8aa7ae --- /dev/null +++ b/csharp/route_guide/RouteGuide/packages.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/csharp/route_guide/RouteGuide/protos/route_guide.proto b/csharp/route_guide/RouteGuide/protos/route_guide.proto new file mode 100644 index 00000000000..f4110b5515b --- /dev/null +++ b/csharp/route_guide/RouteGuide/protos/route_guide.proto @@ -0,0 +1,123 @@ +// 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. + +// TODO(jtattermusch): as of now, C# protobufs don't officially support +// proto3. +syntax = "proto2"; + +package examples; + +// Interface exported by the server. +service RouteGuide { + // A simple RPC. + // + // Obtains the feature at a given position. + // + // A feature with an empty name is returned if there's no feature at the given + // position. + rpc GetFeature(Point) returns (Feature) {} + + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} + + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} + + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} +} + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + optional int32 latitude = 1; + optional int32 longitude = 2; +} + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +message Rectangle { + // One corner of the rectangle. + optional Point lo = 1; + + // The other corner of the rectangle. + optional Point hi = 2; +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +message Feature { + // The name of the feature. + optional string name = 1; + + // The point where the feature is detected. + optional Point location = 2; +} + +// A RouteNote is a message sent while at a given point. +message RouteNote { + // The location from which the message is sent. + optional Point location = 1; + + // The message to be sent. + optional string message = 2; +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +message RouteSummary { + // The number of points received. + optional int32 point_count = 1; + + // The number of known features passed while traversing the route. + optional int32 feature_count = 2; + + // The distance covered in metres. + optional int32 distance = 3; + + // The duration of the traversal in seconds. + optional int32 elapsed_time = 4; +} diff --git a/csharp/route_guide/RouteGuide/route_guide_db.json b/csharp/route_guide/RouteGuide/route_guide_db.json new file mode 100644 index 00000000000..209f0162593 --- /dev/null +++ b/csharp/route_guide/RouteGuide/route_guide_db.json @@ -0,0 +1,601 @@ +[{ + "location": { + "latitude": 407838351, + "longitude": -746143763 + }, + "name": "Patriots Path, Mendham, NJ 07945, USA" +}, { + "location": { + "latitude": 408122808, + "longitude": -743999179 + }, + "name": "101 New Jersey 10, Whippany, NJ 07981, USA" +}, { + "location": { + "latitude": 413628156, + "longitude": -749015468 + }, + "name": "U.S. 6, Shohola, PA 18458, USA" +}, { + "location": { + "latitude": 419999544, + "longitude": -740371136 + }, + "name": "5 Conners Road, Kingston, NY 12401, USA" +}, { + "location": { + "latitude": 414008389, + "longitude": -743951297 + }, + "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" +}, { + "location": { + "latitude": 419611318, + "longitude": -746524769 + }, + "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" +}, { + "location": { + "latitude": 406109563, + "longitude": -742186778 + }, + "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" +}, { + "location": { + "latitude": 416802456, + "longitude": -742370183 + }, + "name": "352 South Mountain Road, Wallkill, NY 12589, USA" +}, { + "location": { + "latitude": 412950425, + "longitude": -741077389 + }, + "name": "Bailey Turn Road, Harriman, NY 10926, USA" +}, { + "location": { + "latitude": 412144655, + "longitude": -743949739 + }, + "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" +}, { + "location": { + "latitude": 415736605, + "longitude": -742847522 + }, + "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" +}, { + "location": { + "latitude": 413843930, + "longitude": -740501726 + }, + "name": "162 Merrill Road, Highland Mills, NY 10930, USA" +}, { + "location": { + "latitude": 410873075, + "longitude": -744459023 + }, + "name": "Clinton Road, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 412346009, + "longitude": -744026814 + }, + "name": "16 Old Brook Lane, Warwick, NY 10990, USA" +}, { + "location": { + "latitude": 402948455, + "longitude": -747903913 + }, + "name": "3 Drake Lane, Pennington, NJ 08534, USA" +}, { + "location": { + "latitude": 406337092, + "longitude": -740122226 + }, + "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" +}, { + "location": { + "latitude": 406421967, + "longitude": -747727624 + }, + "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" +}, { + "location": { + "latitude": 416318082, + "longitude": -749677716 + }, + "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" +}, { + "location": { + "latitude": 415301720, + "longitude": -748416257 + }, + "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" +}, { + "location": { + "latitude": 402647019, + "longitude": -747071791 + }, + "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" +}, { + "location": { + "latitude": 412567807, + "longitude": -741058078 + }, + "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" +}, { + "location": { + "latitude": 416855156, + "longitude": -744420597 + }, + "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" +}, { + "location": { + "latitude": 404663628, + "longitude": -744820157 + }, + "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" +}, { + "location": { + "latitude": 407113723, + "longitude": -749746483 + }, + "name": "" +}, { + "location": { + "latitude": 402133926, + "longitude": -743613249 + }, + "name": "" +}, { + "location": { + "latitude": 400273442, + "longitude": -741220915 + }, + "name": "" +}, { + "location": { + "latitude": 411236786, + "longitude": -744070769 + }, + "name": "" +}, { + "location": { + "latitude": 411633782, + "longitude": -746784970 + }, + "name": "211-225 Plains Road, Augusta, NJ 07822, USA" +}, { + "location": { + "latitude": 415830701, + "longitude": -742952812 + }, + "name": "" +}, { + "location": { + "latitude": 413447164, + "longitude": -748712898 + }, + "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" +}, { + "location": { + "latitude": 405047245, + "longitude": -749800722 + }, + "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" +}, { + "location": { + "latitude": 418858923, + "longitude": -746156790 + }, + "name": "" +}, { + "location": { + "latitude": 417951888, + "longitude": -748484944 + }, + "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" +}, { + "location": { + "latitude": 407033786, + "longitude": -743977337 + }, + "name": "26 East 3rd Street, New Providence, NJ 07974, USA" +}, { + "location": { + "latitude": 417548014, + "longitude": -740075041 + }, + "name": "" +}, { + "location": { + "latitude": 410395868, + "longitude": -744972325 + }, + "name": "" +}, { + "location": { + "latitude": 404615353, + "longitude": -745129803 + }, + "name": "" +}, { + "location": { + "latitude": 406589790, + "longitude": -743560121 + }, + "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" +}, { + "location": { + "latitude": 414653148, + "longitude": -740477477 + }, + "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" +}, { + "location": { + "latitude": 405957808, + "longitude": -743255336 + }, + "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" +}, { + "location": { + "latitude": 411733589, + "longitude": -741648093 + }, + "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" +}, { + "location": { + "latitude": 412676291, + "longitude": -742606606 + }, + "name": "1270 Lakes Road, Monroe, NY 10950, USA" +}, { + "location": { + "latitude": 409224445, + "longitude": -748286738 + }, + "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" +}, { + "location": { + "latitude": 406523420, + "longitude": -742135517 + }, + "name": "652 Garden Street, Elizabeth, NJ 07202, USA" +}, { + "location": { + "latitude": 401827388, + "longitude": -740294537 + }, + "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" +}, { + "location": { + "latitude": 410564152, + "longitude": -743685054 + }, + "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 408472324, + "longitude": -740726046 + }, + "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" +}, { + "location": { + "latitude": 412452168, + "longitude": -740214052 + }, + "name": "5 White Oak Lane, Stony Point, NY 10980, USA" +}, { + "location": { + "latitude": 409146138, + "longitude": -746188906 + }, + "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" +}, { + "location": { + "latitude": 404701380, + "longitude": -744781745 + }, + "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 409642566, + "longitude": -746017679 + }, + "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" +}, { + "location": { + "latitude": 408031728, + "longitude": -748645385 + }, + "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" +}, { + "location": { + "latitude": 413700272, + "longitude": -742135189 + }, + "name": "367 Prospect Road, Chester, NY 10918, USA" +}, { + "location": { + "latitude": 404310607, + "longitude": -740282632 + }, + "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" +}, { + "location": { + "latitude": 409319800, + "longitude": -746201391 + }, + "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" +}, { + "location": { + "latitude": 406685311, + "longitude": -742108603 + }, + "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" +}, { + "location": { + "latitude": 419018117, + "longitude": -749142781 + }, + "name": "43 Dreher Road, Roscoe, NY 12776, USA" +}, { + "location": { + "latitude": 412856162, + "longitude": -745148837 + }, + "name": "Swan Street, Pine Island, NY 10969, USA" +}, { + "location": { + "latitude": 416560744, + "longitude": -746721964 + }, + "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" +}, { + "location": { + "latitude": 405314270, + "longitude": -749836354 + }, + "name": "" +}, { + "location": { + "latitude": 414219548, + "longitude": -743327440 + }, + "name": "" +}, { + "location": { + "latitude": 415534177, + "longitude": -742900616 + }, + "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" +}, { + "location": { + "latitude": 406898530, + "longitude": -749127080 + }, + "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" +}, { + "location": { + "latitude": 407586880, + "longitude": -741670168 + }, + "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" +}, { + "location": { + "latitude": 400106455, + "longitude": -742870190 + }, + "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" +}, { + "location": { + "latitude": 400066188, + "longitude": -746793294 + }, + "name": "" +}, { + "location": { + "latitude": 418803880, + "longitude": -744102673 + }, + "name": "40 Mountain Road, Napanoch, NY 12458, USA" +}, { + "location": { + "latitude": 414204288, + "longitude": -747895140 + }, + "name": "" +}, { + "location": { + "latitude": 414777405, + "longitude": -740615601 + }, + "name": "" +}, { + "location": { + "latitude": 415464475, + "longitude": -747175374 + }, + "name": "48 North Road, Forestburgh, NY 12777, USA" +}, { + "location": { + "latitude": 404062378, + "longitude": -746376177 + }, + "name": "" +}, { + "location": { + "latitude": 405688272, + "longitude": -749285130 + }, + "name": "" +}, { + "location": { + "latitude": 400342070, + "longitude": -748788996 + }, + "name": "" +}, { + "location": { + "latitude": 401809022, + "longitude": -744157964 + }, + "name": "" +}, { + "location": { + "latitude": 404226644, + "longitude": -740517141 + }, + "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" +}, { + "location": { + "latitude": 410322033, + "longitude": -747871659 + }, + "name": "" +}, { + "location": { + "latitude": 407100674, + "longitude": -747742727 + }, + "name": "" +}, { + "location": { + "latitude": 418811433, + "longitude": -741718005 + }, + "name": "213 Bush Road, Stone Ridge, NY 12484, USA" +}, { + "location": { + "latitude": 415034302, + "longitude": -743850945 + }, + "name": "" +}, { + "location": { + "latitude": 411349992, + "longitude": -743694161 + }, + "name": "" +}, { + "location": { + "latitude": 404839914, + "longitude": -744759616 + }, + "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 414638017, + "longitude": -745957854 + }, + "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" +}, { + "location": { + "latitude": 412127800, + "longitude": -740173578 + }, + "name": "" +}, { + "location": { + "latitude": 401263460, + "longitude": -747964303 + }, + "name": "" +}, { + "location": { + "latitude": 412843391, + "longitude": -749086026 + }, + "name": "" +}, { + "location": { + "latitude": 418512773, + "longitude": -743067823 + }, + "name": "" +}, { + "location": { + "latitude": 404318328, + "longitude": -740835638 + }, + "name": "42-102 Main Street, Belford, NJ 07718, USA" +}, { + "location": { + "latitude": 419020746, + "longitude": -741172328 + }, + "name": "" +}, { + "location": { + "latitude": 404080723, + "longitude": -746119569 + }, + "name": "" +}, { + "location": { + "latitude": 401012643, + "longitude": -744035134 + }, + "name": "" +}, { + "location": { + "latitude": 404306372, + "longitude": -741079661 + }, + "name": "" +}, { + "location": { + "latitude": 403966326, + "longitude": -748519297 + }, + "name": "" +}, { + "location": { + "latitude": 405002031, + "longitude": -748407866 + }, + "name": "" +}, { + "location": { + "latitude": 409532885, + "longitude": -742200683 + }, + "name": "" +}, { + "location": { + "latitude": 416851321, + "longitude": -742674555 + }, + "name": "" +}, { + "location": { + "latitude": 406411633, + "longitude": -741722051 + }, + "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" +}, { + "location": { + "latitude": 413069058, + "longitude": -744597778 + }, + "name": "261 Van Sickle Road, Goshen, NY 10924, USA" +}, { + "location": { + "latitude": 418465462, + "longitude": -746859398 + }, + "name": "" +}, { + "location": { + "latitude": 411733222, + "longitude": -744228360 + }, + "name": "" +}, { + "location": { + "latitude": 410248224, + "longitude": -747127767 + }, + "name": "3 Hasta Way, Newton, NJ 07860, USA" +}] \ No newline at end of file diff --git a/csharp/route_guide/RouteGuideClient/App.config b/csharp/route_guide/RouteGuideClient/App.config new file mode 100644 index 00000000000..8e15646352e --- /dev/null +++ b/csharp/route_guide/RouteGuideClient/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/csharp/route_guide/RouteGuideClient/Program.cs b/csharp/route_guide/RouteGuideClient/Program.cs new file mode 100644 index 00000000000..0352c780201 --- /dev/null +++ b/csharp/route_guide/RouteGuideClient/Program.cs @@ -0,0 +1,223 @@ +using Grpc.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace examples +{ + class Program + { + /// + /// Sample client code that makes gRPC calls to the server. + /// + public class RouteGuideClient + { + readonly RouteGuide.IRouteGuideClient client; + + public RouteGuideClient(RouteGuide.IRouteGuideClient client) + { + this.client = client; + } + + /// + /// Blocking unary call example. Calls GetFeature and prints the response. + /// + public void GetFeature(int lat, int lon) + { + try + { + Log("*** GetFeature: lat={0} lon={1}", lat, lon); + + Point request = Point.CreateBuilder().SetLatitude(lat).SetLongitude(lon).Build(); + + Feature feature = client.GetFeature(request); + if (RouteGuideUtil.Exists(feature)) + { + Log("Found feature called \"{0}\" at {1}, {2}", + feature.Name, + RouteGuideUtil.GetLatitude(feature.Location), + RouteGuideUtil.GetLongitude(feature.Location)); + } + else + { + Log("Found no feature at {0}, {1}", + RouteGuideUtil.GetLatitude(feature.Location), + RouteGuideUtil.GetLongitude(feature.Location)); + } + } + catch (RpcException e) + { + Log("RPC failed " + e); + throw e; + } + } + + + /// + /// Server-streaming example. Calls listFeatures with a rectangle of interest. Prints each response feature as it arrives. + /// + public async Task ListFeatures(int lowLat, int lowLon, int hiLat, int hiLon) + { + try + { + Log("*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}", lowLat, lowLon, hiLat, + hiLon); + + Rectangle request = + Rectangle.CreateBuilder() + .SetLo(Point.CreateBuilder().SetLatitude(lowLat).SetLongitude(lowLon).Build()) + .SetHi(Point.CreateBuilder().SetLatitude(hiLat).SetLongitude(hiLon).Build()).Build(); + + using (var call = client.ListFeatures(request)) + { + StringBuilder responseLog = new StringBuilder("Result: "); + + while (await call.ResponseStream.MoveNext()) + { + Feature feature = call.ResponseStream.Current; + responseLog.Append(feature.ToString()); + } + Log(responseLog.ToString()); + } + } + catch (RpcException e) + { + Log("RPC failed " + e); + throw e; + } + } + + /// + /// Client-streaming example. Sends numPoints randomly chosen points from features + /// with a variable delay in between. Prints the statistics when they are sent from the server. + /// + public async Task RecordRoute(List features, int numPoints) + { + try + { + Log("*** RecordRoute"); + using (var call = client.RecordRoute()) + { + // Send numPoints points randomly selected from the features list. + StringBuilder numMsg = new StringBuilder(); + Random rand = new Random(); + for (int i = 0; i < numPoints; ++i) + { + int index = rand.Next(features.Count); + Point point = features[index].Location; + Log("Visiting point {0}, {1}", RouteGuideUtil.GetLatitude(point), + RouteGuideUtil.GetLongitude(point)); + + await call.RequestStream.WriteAsync(point); + + // A bit of delay before sending the next one. + await Task.Delay(rand.Next(1000) + 500); + } + await call.RequestStream.CompleteAsync(); + + RouteSummary summary = await call.Result; + Log("Finished trip with {0} points. Passed {1} features. " + + "Travelled {2} meters. It took {3} seconds.", summary.PointCount, + summary.FeatureCount, summary.Distance, summary.ElapsedTime); + + Log("Finished RecordRoute"); + } + } + catch (RpcException e) + { + Log("RPC failed", e); + throw e; + } + } + + /// + /// Bi-directional streaming example. Send some chat messages, and print any + /// chat messages that are sent from the server. + /// + public async Task RouteChat() + { + try + { + Log("*** RouteChat"); + var requests = + new List { NewNote("First message", 0, 0), NewNote("Second message", 0, 1), NewNote("Third message", 1, 0), NewNote("Fourth message", 1, 1) }; + + using (var call = client.RouteChat()) + { + var responseReaderTask = Task.Run(async () => + { + while (await call.ResponseStream.MoveNext()) + { + var note = call.ResponseStream.Current; + Log("Got message \"{0}\" at {1}, {2}", note.Message, + note.Location.Latitude, note.Location.Longitude); + } + }); + + foreach (RouteNote request in requests) + { + Log("Sending message \"{0}\" at {1}, {2}", request.Message, + request.Location.Latitude, request.Location.Longitude); + + await call.RequestStream.WriteAsync(request); + } + await call.RequestStream.CompleteAsync(); + await responseReaderTask; + + Log("Finished RouteChat"); + } + } + catch (RpcException e) + { + Log("RPC failed", e); + throw e; + } + } + + private void Log(string s, params object[] args) + { + Console.WriteLine(string.Format(s, args)); + } + + private void Log(string s) + { + Console.WriteLine(s); + } + + private RouteNote NewNote(string message, int lat, int lon) + { + return RouteNote.CreateBuilder().SetMessage(message).SetLocation( + Point.CreateBuilder().SetLatitude(lat).SetLongitude(lat).Build()).Build(); + } + } + + static void Main(string[] args) + { + GrpcEnvironment.Initialize(); + + using (Channel channel = new Channel("127.0.0.1:50052")) + { + var client = new RouteGuideClient(RouteGuide.NewStub(channel)); + + // Looking for a valid feature + client.GetFeature(409146138, -746188906); + + // Feature missing. + client.GetFeature(0, 0); + + // Looking for features between 40, -75 and 42, -73. + client.ListFeatures(400000000, -750000000, 420000000, -730000000).Wait(); + + // Record a few randomly selected points from the features file. + client.RecordRoute(RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile), 10).Wait(); + + // Send and receive some notes. + client.RouteChat().Wait(); + } + + GrpcEnvironment.Shutdown(); + } + } +} diff --git a/csharp/route_guide/RouteGuideClient/Properties/AssemblyInfo.cs b/csharp/route_guide/RouteGuideClient/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..a17e164a788 --- /dev/null +++ b/csharp/route_guide/RouteGuideClient/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RouteGuideClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RouteGuideClient")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("914644eb-47cd-4a37-9fba-5e62dd432333")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj b/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj new file mode 100644 index 00000000000..988db6a5db7 --- /dev/null +++ b/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj @@ -0,0 +1,98 @@ + + + + + + + + Debug + AnyCPU + {D47BE663-4DE3-4206-B7A8-EA3FA066DADC} + Exe + Properties + RouteGuideClient + RouteGuideClient + v4.5 + 512 + c0fbb9f1 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll + + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll + + + ..\packages\Grpc.Core.0.5.0\lib\net45\Grpc.Core.dll + + + + ..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + + + ..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll + + + + + + + + + + + + + + + + + + {49954d9c-5f17-4662-96b2-73be833dd81a} + RouteGuide + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + \ No newline at end of file diff --git a/csharp/route_guide/RouteGuideClient/packages.config b/csharp/route_guide/RouteGuideClient/packages.config new file mode 100644 index 00000000000..b1f8c6945e4 --- /dev/null +++ b/csharp/route_guide/RouteGuideClient/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/csharp/route_guide/RouteGuideServer/App.config b/csharp/route_guide/RouteGuideServer/App.config new file mode 100644 index 00000000000..8e15646352e --- /dev/null +++ b/csharp/route_guide/RouteGuideServer/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/csharp/route_guide/RouteGuideServer/Program.cs b/csharp/route_guide/RouteGuideServer/Program.cs new file mode 100644 index 00000000000..e00b4d67238 --- /dev/null +++ b/csharp/route_guide/RouteGuideServer/Program.cs @@ -0,0 +1,30 @@ +using Grpc.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace examples +{ + class Program + { + static void Main(string[] args) + { + var features = RouteGuideUtil.ParseFeatures(RouteGuideUtil.DefaultFeaturesFile); + GrpcEnvironment.Initialize(); + + Server server = new Server(); + server.AddServiceDefinition(RouteGuide.BindService(new RouteGuideImpl(features))); + int port = server.AddListeningPort("localhost", 50052); + server.Start(); + + Console.WriteLine("RouteGuide server listening on port " + port); + Console.WriteLine("Press any key to stop the server..."); + Console.ReadKey(); + + server.ShutdownAsync().Wait(); + GrpcEnvironment.Shutdown(); + } + } +} diff --git a/csharp/route_guide/RouteGuideServer/Properties/AssemblyInfo.cs b/csharp/route_guide/RouteGuideServer/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..a161b1d6027 --- /dev/null +++ b/csharp/route_guide/RouteGuideServer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RouteGuideServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RouteGuideServer")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("908bdeef-05cc-42bf-9498-c4c573df8925")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs b/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs new file mode 100644 index 00000000000..0bdf386fc33 --- /dev/null +++ b/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace examples +{ + /// + /// Example implementation of RouteGuide server. + /// + public class RouteGuideImpl : RouteGuide.IRouteGuide + { + readonly List features; + private readonly ConcurrentDictionary> routeNotes = + new ConcurrentDictionary>(); + + public RouteGuideImpl(List features) + { + this.features = features; + } + + /// + /// Gets the feature at the requested point. If no feature at that location + /// exists, an unnammed feature is returned at the provided location. + /// + public Task GetFeature(Grpc.Core.ServerCallContext context, Point request) + { + return Task.FromResult(CheckFeature(request)); + } + + /// + /// Gets all features contained within the given bounding rectangle. + /// + public async Task ListFeatures(Grpc.Core.ServerCallContext context, Rectangle request, Grpc.Core.IServerStreamWriter responseStream) + { + int left = Math.Min(request.Lo.Longitude, request.Hi.Longitude); + int right = Math.Max(request.Lo.Longitude, request.Hi.Longitude); + int top = Math.Max(request.Lo.Latitude, request.Hi.Latitude); + int bottom = Math.Min(request.Lo.Latitude, request.Hi.Latitude); + + foreach (var feature in features) + { + if (!RouteGuideUtil.Exists(feature)) + { + continue; + } + + int lat = feature.Location.Latitude; + int lon = feature.Location.Longitude; + if (lon >= left && lon <= right && lat >= bottom && lat <= top) + { + await responseStream.WriteAsync(feature); + } + } + } + + /// + /// Gets a stream of points, and responds with statistics about the "trip": number of points, + /// number of known features visited, total distance traveled, and total time spent. + /// + public async Task RecordRoute(Grpc.Core.ServerCallContext context, Grpc.Core.IAsyncStreamReader requestStream) + { + int pointCount = 0; + int featureCount = 0; + int distance = 0; + Point previous = null; + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + while (await requestStream.MoveNext()) + { + var point = requestStream.Current; + pointCount++; + if (RouteGuideUtil.Exists(CheckFeature(point))) + { + featureCount++; + } + if (previous != null) + { + distance += (int) CalcDistance(previous, point); + } + previous = point; + } + + stopwatch.Stop(); + return RouteSummary.CreateBuilder().SetPointCount(pointCount) + .SetFeatureCount(featureCount).SetDistance(distance) + .SetElapsedTime((int) (stopwatch.ElapsedMilliseconds / 1000)).Build(); + } + + /// + /// Receives a stream of message/location pairs, and responds with a stream of all previous + /// messages at each of those locations. + /// + public async Task RouteChat(Grpc.Core.ServerCallContext context, Grpc.Core.IAsyncStreamReader requestStream, Grpc.Core.IServerStreamWriter responseStream) + { + while (await requestStream.MoveNext()) + { + var note = requestStream.Current; + List notes = GetOrCreateNotes(note.Location); + + List prevNotes; + lock (notes) + { + prevNotes = new List(notes); + } + + foreach (var prevNote in prevNotes) + { + await responseStream.WriteAsync(prevNote); + } + + lock (notes) + { + notes.Add(note); + } + } + } + + + /// + /// Get the notes list for the given location. If missing, create it. + /// + private List GetOrCreateNotes(Point location) + { + List notes = new List(); + routeNotes.TryAdd(location, notes); + return routeNotes[location]; + } + + /// + /// Gets the feature at the given point. + /// + /// the location to check + /// The feature object at the point Note that an empty name indicates no feature. + private Feature CheckFeature(Point location) + { + foreach (var feature in features) + { + if (feature.Location.Latitude == location.Latitude + && feature.Location.Longitude == location.Longitude) + { + return feature; + } + } + + // No feature was found, return an unnamed feature. + return Feature.CreateBuilder().SetName("").SetLocation(location).Build(); + } + + /// + /// Calculate the distance between two points using the "haversine" formula. + /// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html. + /// + /// the starting point + /// the end point + /// the distance between the points in meters + private static double CalcDistance(Point start, Point end) + { + double lat1 = RouteGuideUtil.GetLatitude(start); + double lat2 = RouteGuideUtil.GetLatitude(end); + double lon1 = RouteGuideUtil.GetLongitude(start); + double lon2 = RouteGuideUtil.GetLongitude(end); + int r = 6371000; // metres + double φ1 = ToRadians(lat1); + double φ2 = ToRadians(lat2); + double Δφ = ToRadians(lat2 - lat1); + double Δλ = ToRadians(lon2 - lon1); + + double a = Math.Sin(Δφ / 2) * Math.Sin(Δφ / 2) + Math.Cos(φ1) * Math.Cos(φ2) * Math.Sin(Δλ / 2) * Math.Sin(Δλ / 2); + double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); + + return r * c; + } + + private static double ToRadians(double val) + { + return (Math.PI / 180) * val; + } + } +} diff --git a/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj b/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj new file mode 100644 index 00000000000..3fb7740ef7b --- /dev/null +++ b/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj @@ -0,0 +1,99 @@ + + + + + + + + Debug + AnyCPU + {4B7C7794-BE24-4477-ACE7-18259EB73D27} + Exe + Properties + RouteGuideServer + RouteGuideServer + v4.5 + 512 + 93b8fc4b + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll + + + ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll + + + ..\packages\Grpc.Core.0.5.0\lib\net45\Grpc.Core.dll + + + + ..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + + + ..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll + + + + + + + + + + + + + + + + + + + {49954d9c-5f17-4662-96b2-73be833dd81a} + RouteGuide + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + \ No newline at end of file diff --git a/csharp/route_guide/RouteGuideServer/packages.config b/csharp/route_guide/RouteGuideServer/packages.config new file mode 100644 index 00000000000..b1f8c6945e4 --- /dev/null +++ b/csharp/route_guide/RouteGuideServer/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file