Given ReadOnlySequence<byte>
, how to get its base64-encoded representation?
There's ReadOnlySpan<Byte>
overload, but sequence is... a sequence of spans, not a single span.
I know, that it's possible to make an array from sequence, but this is what I want to avoid: I use RecyclableMemoryStream
and trying to avoid extra memory allocations.
Any solution?
CodePudding user response:
You need something which can keep state as you pass in different blocks of bytes. That thing is a ToBase64Transform
.
Annoyingly, none of the methods on it take a Memory or ROS (apart from the async
ones) -- they're all array-based. I guess you could have a scratch array which you copy chunks into, then pass those chunks to ToBase64Transform
, but at that point you might as well just use Convert.ToBase64String
on each chunk and concatenate the results.
You could pass ToBase64Transform
to a CryptoStream
. You could then call Stream.Write(ReadOnlySpan<byte>)
, but that's implemented to copy the span into an array (and CryptoStream
doesn't override this), which is what you're trying to avoid.
However, CryptoStream
does override WriteByte
, so that might be your best bet.
Something like:
using var writer = new StringWriter();
using (var stream = new CryptoStream(writer, new ToBase64Transform(), CryptoStreamMode.Write))
{
foreach (var memory in readOnlySequence)
{
if (MemoryMarshal.TryGetArray(memory, out var segment))
{
stream.Write(segment.Array, segment.Offset, segment.Count);
}
else
{
var span = memory.Span;
for (int i = 0; i < span.Length; i )
{
stream.WriteByte(span[i]);
}
}
}
}
string result = writer.ToString();
At this point, though, it's looking like it might be neater to just use Base64.EncodeToUtf8
and a StringWriter
yourself, manually...