-
Notifications
You must be signed in to change notification settings - Fork 15.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ByteString.FromStream and ByteString.FromStreamAsync in C#
Fixes #2088. We now have separate tests for netcoreapp and net45 to test the two branches here. (netstandard10 doesn't have MemoryStream.GetBuffer) Although most of this library doesn't have any async functionality, this feels like a natural place to locally add it.
- Loading branch information
Showing
3 changed files
with
108 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,10 @@ | |
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
#if !DOTNET35 | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
#endif | ||
|
||
namespace Google.Protobuf | ||
{ | ||
|
@@ -141,6 +145,55 @@ public static ByteString FromBase64(string bytes) | |
return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes)); | ||
} | ||
|
||
/// <summary> | ||
/// Constructs a <see cref="ByteString"/> from data in the given stream, synchronously. | ||
/// </summary> | ||
/// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position | ||
/// at the start of the call.</remarks> | ||
/// <param name="stream">The stream to copy into a ByteString.</param> | ||
/// <returns>A ByteString with content read from the given stream.</returns> | ||
public static ByteString FromStream(Stream stream) | ||
{ | ||
ProtoPreconditions.CheckNotNull(stream, nameof(stream)); | ||
int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
var memoryStream = new MemoryStream(capacity); | ||
This comment has been minimized.
Sorry, something went wrong.
patspam
|
||
stream.CopyTo(memoryStream); | ||
#if NETSTANDARD1_0 | ||
byte[] bytes = memoryStream.ToArray(); | ||
#else | ||
// Avoid an extra copy if we can. | ||
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray(); | ||
#endif | ||
return AttachBytes(bytes); | ||
} | ||
|
||
#if !DOTNET35 | ||
/// <summary> | ||
/// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously. | ||
/// </summary> | ||
/// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position | ||
/// at the start of the call.</remarks> | ||
/// <param name="stream">The stream to copy into a ByteString.</param> | ||
/// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param> | ||
/// <returns>A ByteString with content read from the given stream.</returns> | ||
public async static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) | ||
{ | ||
ProtoPreconditions.CheckNotNull(stream, nameof(stream)); | ||
int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0; | ||
var memoryStream = new MemoryStream(capacity); | ||
// We have to specify the buffer size here, as there's no overload accepting the cancellation token | ||
// alone. But it's documented to use 81920 by default if not specified. | ||
await stream.CopyToAsync(memoryStream, 81920, cancellationToken); | ||
#if NETSTANDARD1_0 | ||
byte[] bytes = memoryStream.ToArray(); | ||
#else | ||
// Avoid an extra copy if we can. | ||
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray(); | ||
#endif | ||
return AttachBytes(bytes); | ||
} | ||
#endif | ||
|
||
/// <summary> | ||
/// Constructs a <see cref="ByteString" /> from the given array. The contents | ||
/// are copied, so further modifications to the array will not | ||
|
Should we be concerned that this MemoryStream is not being disposed?
var memoryStream = new MemoryStream(capacity);