Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protobuf scalar default values and ByteString detail #19769

Merged
merged 1 commit into from Sep 16, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 37 additions & 10 deletions aspnetcore/grpc/protobuf.md
Expand Up @@ -69,6 +69,10 @@ Protobuf supports a range of native scalar value types. The following table list
| `string` | `string` |
| `bytes` | `ByteString` |

Scalar values always have a default value and can't be set to `null`. This constraint includes `string` and `ByteString` which are C# classes. `string` defaults to an empty string value and `ByteString` defaults to an empty bytes value. Attempting to set them to `null` throws an error.

[Nullable wrapper types](#nullable-types) can be used to support null values.

### Dates and times

The native scalar types don't provide for date and time values, equivalent to .NET's <xref:System.DateTimeOffset>, <xref:System.DateTime>, and <xref:System.TimeSpan>. These types can be specified by using some of Protobuf's *Well-Known Types* extensions. These extensions provide code generation and runtime support for complex field types across the supported platforms.
Expand Down Expand Up @@ -129,19 +133,42 @@ message Person {
}
```

Protobuf uses .NET nullable types, for example, `int?`, for the generated message property.
`wrappers.proto` types aren't exposed in generated properties. Protobuf automatically maps them to appropriate .NET nullable types in C# messages. For example, a `google.protobuf.Int32Value` field generates an `int?` property. Reference type properties like `string` and `ByteString` are unchanged except `null` can be assigned to them without error.

The following table shows the complete list of wrapper types with their equivalent C# type:

| C# type | Well-Known Type wrapper |
| --------- | ----------------------------- |
| `bool?` | `google.protobuf.BoolValue` |
| `double?` | `google.protobuf.DoubleValue` |
| `float?` | `google.protobuf.FloatValue` |
| `int?` | `google.protobuf.Int32Value` |
| `long?` | `google.protobuf.Int64Value` |
| `uint?` | `google.protobuf.UInt32Value` |
| `ulong?` | `google.protobuf.UInt64Value` |
| C# type | Well-Known Type wrapper |
| ------------ | ----------------------------- |
| `bool?` | `google.protobuf.BoolValue` |
| `double?` | `google.protobuf.DoubleValue` |
| `float?` | `google.protobuf.FloatValue` |
| `int?` | `google.protobuf.Int32Value` |
| `long?` | `google.protobuf.Int64Value` |
| `uint?` | `google.protobuf.UInt32Value` |
| `ulong?` | `google.protobuf.UInt64Value` |
| `string` | `google.protobuf.StringValue` |
| `ByteString` | `google.protobuf.BytesValue` |

### Bytes

Binary payloads are supported in Protobuf with the `bytes` scalar value type. A generated property in C# uses `ByteString` as the property type.

Use `ByteString.CopyFrom(byte[] data)` to create a new instance from a byte array:

```csharp
var data = await File.ReadAllBytesAsync(path);

var payload = new PayloadResponse();
payload.Data = ByteString.CopyFrom(data);
```

`ByteString` data is accessed directly using `ByteString.Span` or `ByteString.Memory`. Or call `ByteString.ToByteArray()` to convert an instance back into a byte array:

```csharp
var payload = await client.GetPayload(new PayloadRequest());

await File.WriteAllBytesAsync(path, payload.Data.ToByteArray());
```

### Decimals

Expand Down