internal static async Task WriteFinalFromBase64Urlsafe( this Stream stream, Memory <byte> base64Memory, CancellationToken cancelToken = default) { int base64Count = CommonBase64UrlSafe.RevertUrlSafeUtf8(base64Memory.Span, out int base64PadCount); int base64Length = base64Memory.Length + base64PadCount; using (var base64FinalBuffer = bytesPool.Rent(base64Length)) { Memory <byte> base64FinalMemory = base64FinalBuffer.Memory; base64Memory.CopyTo(base64FinalMemory); Memory <byte> base64PadMemory = base64FinalMemory.Slice(base64Memory.Length, base64PadCount); base64PadMemory.Span.Fill(base64PadByte); int bytesRequired = Base64.GetMaxDecodedFromUtf8Length(base64Count + base64PadCount); int base64Consumed = await stream.WritePartialFromBase64( base64FinalMemory.Slice(0, base64Length), bytesRequired, isFinalBlock : true, cancelToken).ConfigureAwait(false); if (base64Consumed < base64Length) { throw new InvalidOperationException("Base64 decode of final block did not consume all bytes"); } } }
internal static async Task <(int base64Remaining, int base64PadCount)> WritePartialFromBase64Urlsafe( this Stream stream, Memory <byte> base64Memory, CancellationToken cancelToken = default) { int base64Count = CommonBase64UrlSafe.RevertUrlSafeUtf8(base64Memory.Span, out int base64PaddingRequired); int bytesRequired = Base64.GetMaxDecodedFromUtf8Length(base64Count); int base64Consumed = await stream.WritePartialFromBase64(base64Memory, bytesRequired, isFinalBlock : false, cancelToken) .ConfigureAwait(false); Memory <byte> base64Remaining = base64Memory.Slice(base64Consumed); base64Remaining.CopyTo(base64Memory); return(base64Remaining.Length, base64PaddingRequired); }
private static async Task <int> WritePartialToBase64Urlsafe( this PipeWriter base64Pipe, Memory <byte> bytesMemory, bool isFinalBlock = true, CancellationToken cancelToken = default) { int base64Required = Base64.GetMaxEncodedToUtf8Length(bytesMemory.Length); Memory <byte> base64Memory = base64Pipe.GetMemory(base64Required); var base64Status = Base64.EncodeToUtf8(bytesMemory.Span, base64Memory.Span, out int bytesConsumed, out int base64Written, isFinalBlock); base64Status.ThrowIfFailed(nameof(Base64.EncodeToUtf8), isFinalBlock); base64Written = CommonBase64UrlSafe.MakeUrlSafeUtf8( base64Memory.Slice(0, base64Written).Span ); base64Pipe.Advance(base64Written); await base64Pipe.FlushAsync(cancelToken).ConfigureAwait(false); return(bytesConsumed); }