Understand what code is generated by protoc-gen-grpc-swift from a .proto
file and how to use it.
The gRPC Swift Protobuf package provides a plugin to the Protocol Buffers
Compiler (protoc) called protoc-gen-grpc-swift. The plugin is responsible
for generating the gRPC specific code for services defined in a .proto file.
Most .proto files contain a package directive near the start of the file
describing the namespace it belongs to. Here's an example:
package foo.bar.v1;
The package name "foo.bar.v1" is important as it is used as a prefix for generated types. The default behaviour is to replace periods with underscores and to capitalize each word and add a trailing underscore. For this package the prefix is "Foo_Bar_V1_". If you don't declare a package then the prefix will be the empty string.
You can override the prefix by setting the swift_prefix option:
option swift_prefix = "FooBarV1";
package foo.bar.v1;
The prefix for types in this file would be "FooBarV1" instead of "Foo_Bar_V1_".
For each service declared in your .proto file, gRPC will generate a caseless
enum which is a namespace holding the generated protocols and types. The name
of this enum is {PREFIX}{SERVICE} where {PREFIX} is as described in the
previous section and {SERVICE} is the name of the service as declared in the
.proto file.
As an example the following definition creates a service namespace enum called
Foo_Bar_V1_BazService (the {PREFIX} is "Foo_BarV1" and {SERVICE} is
"BazService"):
package foo.bar.v1;
service BazService {
// ...
}
Code generated for each service falls into three categories:
gRPC generates metadata for each service including a descriptor identifying the fully qualified name of the service and information about each method in the service. You likely won't need to interact directly with this information but it's available should you need to.
Within a service namespace gRPC generates three service protocols:
StreamingServiceProtocol,ServiceProtocol, andSimpleServiceProtocol.The full name of each protocol includes the service namespace.
Example:
For the
BazServicein thefoo.bar.v1package the protocols would be:
Foo_Bar_V1_BazService.StreamingServiceProtocol,Foo_Bar_V1_BazService.ServiceProtocol, andFoo_Bar_V1_BazService.SimpleServiceProtocol.
Each of these protocols mirror the service defined in your .proto file with
one requirement per RPC. To implement your service you must implement one of
these protocols.
The protocols form a hierarchy with StreamingServiceProtocol at the bottom and
SimpleServiceProtocol at the top. ServiceProtocol refines
StreamingServiceProtocol, and SimpleServiceProtocol refines
ServiceProtocol (and StreamingServiceProtocol in turn).
The StreamingServiceProtocol implements each RPC as if it were a bidirectional
streaming RPC. This gives you the most flexibility at the cost of a harder to
implement API. It also puts the responsibility on you to ensure that each RPC
sends and receives the correct number of messages.
The ServiceProtocol enforces that the correct number of messages are sent and
received via its API. It also allows you to read request metadata and send both
initial and trailing metadata. The request and response types for these
requirements are in terms of ServerRequest and ServerResponse.
The SimpleServiceProtocol also enforces the correct number of messages are
sent and received via its API. However, it isn't defined in terms of
ServerRequest or ServerResponse so it doesn't allow you access metadata.
This limitation allows it to have the simplest API and is preferred if you don't
need access to metadata.
| Protocol | Enforces number of messages | Access to metadata |
|---|---|---|
StreamingServiceProtocol |
✗ | ✓ |
ServiceProtocol |
✓ | ✓ |
SimpleServiceProtocol |
✓ | ✗ |
gRPC generates two types for the client within a service namespace:
ClientProtocol, andClient.Like the service code, the full name includes the namespace.
Example:
For the
BazServicein thefoo.bar.v1package the client types would be:
Foo_Bar_V1_BazService.ClientProtocol, andFoo_Bar_V1_BazService.Client.
The ClientProtocol defines one requirement for each RPC in terms of
ClientRequest and ClientResponse. You don't need to implement the protocol
as Client provides a concrete implementation.
gRPC also generates extensions on ClientProtocol to provide more ergonomic
APIs. These include versions which provide default arguments for various
parameters (like the message serializer and deserializers; call options and
response handler) and versions which don't use ClientRequest and
ClientResponse directly.