Skip to content

Commit

Permalink
Protobuf scalar default values and ByteString detail
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK committed Sep 3, 2020
1 parent a3dcf32 commit 03b7e08
Showing 1 changed file with 37 additions and 10 deletions.
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

0 comments on commit 03b7e08

Please sign in to comment.