DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.15.1" />

 Base64Decoder

public struct Base64Decoder : IResettable
Represents base64 decoder suitable for decoding large base64-encoded binary data using streaming approach.
using DotNext.IO; using System; using System.Buffers; using System.Buffers.Text; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; namespace DotNext.Buffers.Text { [StructLayout(LayoutKind.Auto)] [DebuggerDisplay("NeedMoreData = {NeedMoreData}")] public struct Base64Decoder : IResettable { private const int DecodingBufferSize = 258; private const int GotPaddingFlag = -1; private ulong reservedBuffer; private int reservedBufferSize; private const char PaddingChar = '='; private const byte PaddingByte = 61; public bool NeedMoreData { [IsReadOnly] get { return reservedBufferSize > 0; } } public void Reset() { reservedBufferSize = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Span<char> AsChars(ref ulong value) { return MemoryMarshal.CreateSpan(ref Unsafe.As<ulong, char>(ref value), 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ReadOnlySpan<char> AsChars([In] [IsReadOnly] ref ulong value, int length) { return MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As<ulong, char>(ref Unsafe.AsRef(ref value)), length); } private bool DecodeFromUtf16Core<TWriter>([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, [LifetimeAnnotation(true, false)] ref TWriter writer) where TWriter : IBufferWriter<byte> { int bytesWritten = chars.Length & 3; if (bytesWritten != 0) { bytesWritten = chars.Length - bytesWritten; ReadOnlySpan<char> readOnlySpan = chars.Slice(bytesWritten); readOnlySpan.CopyTo(AsChars(ref reservedBuffer)); reservedBufferSize = readOnlySpan.Length; chars = chars.Slice(0, bytesWritten); } else { int length = chars.Length; if (length >= 1 && chars[length - 1] == '=') reservedBufferSize = -1; else reservedBufferSize = 0; } bool num = Convert.TryFromBase64Chars(chars, ((IBufferWriter<byte>)writer).GetSpan(chars.Length), out bytesWritten); if (num) ((IBufferWriter<byte>)writer).Advance(bytesWritten); return num; } [SkipLocalsInit] private unsafe bool CopyAndDecodeFromUtf16<TWriter>([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, [LifetimeAnnotation(true, false)] ref TWriter writer) where TWriter : IBufferWriter<byte> { int num = reservedBufferSize + chars.Length; MemoryRental<char> memoryRental; if ((uint)num > (uint)MemoryRental<char>.StackallocThreshold) memoryRental = new MemoryRental<char>(num, true); else { int num2 = num; memoryRental = new Span<char>((void*)stackalloc byte[(int)checked(unchecked((ulong)(uint)num2) * 2)], num2); } MemoryRental<char> memoryRental2 = memoryRental; try { AsChars(ref reservedBuffer, reservedBufferSize).CopyTo(memoryRental2.Span); chars.CopyTo(memoryRental2.Span.Slice(reservedBufferSize)); return DecodeFromUtf16Core(memoryRental2.Span, ref writer); } finally { memoryRental2.Dispose(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool DecodeFromUtf16<TWriter>([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, [LifetimeAnnotation(true, false)] ref TWriter writer) where TWriter : IBufferWriter<byte> { switch (reservedBufferSize) { case -1: return false; case 0: return DecodeFromUtf16Core(chars, ref writer); default: return CopyAndDecodeFromUtf16(chars, ref writer); } } public void DecodeFromUtf16([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, [System.Runtime.CompilerServices.Nullable(1)] IBufferWriter<byte> output) { ArgumentNullException.ThrowIfNull((object)output, "output"); if (!DecodeFromUtf16(chars, ref output)) throw new FormatException(ExceptionMessages.MalformedBase64); } public void DecodeFromUtf16([In] [LifetimeAnnotation(true, false)] [IsReadOnly] ref ReadOnlySequence<char> chars, [System.Runtime.CompilerServices.Nullable(1)] IBufferWriter<byte> output) { ArgumentNullException.ThrowIfNull((object)output, "output"); ReadOnlySequence<char>.Enumerator enumerator = chars.GetEnumerator(); do { if (!enumerator.MoveNext()) return; } while (DecodeFromUtf16(enumerator.Current.Span, ref output)); throw new FormatException(ExceptionMessages.MalformedBase64); } public MemoryOwner<byte> DecodeFromUtf16([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, [System.Runtime.CompilerServices.Nullable(2)] MemoryAllocator<byte> allocator = null) { MemoryOwnerWrapper<byte> writer = new MemoryOwnerWrapper<byte>(allocator); if (chars.IsEmpty || DecodeFromUtf16(chars, ref writer)) return writer.Buffer; writer.Buffer.Dispose(); throw new FormatException(ExceptionMessages.MalformedBase64); } [SkipLocalsInit] private unsafe void DecodeFromUtf16Core<TConsumer>([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, TConsumer output) where TConsumer : IReadOnlySpanConsumer<byte> { Span<byte> output2 = new Span<byte>((void*)stackalloc byte[258], 258); do { ReadOnlySpan<char> input = chars.TrimLength(344); if (!<DecodeFromUtf16Core>g__Decode|16_0<TConsumer>(input, output2, out int consumedChars, out int producedBytes, ref reservedBufferSize)) { reservedBufferSize = input.Length - consumedChars; input.Slice(consumedChars).CopyTo(AsChars(ref reservedBuffer)); } if (consumedChars == 0 || producedBytes == 0) break; ((IReadOnlySpanConsumer<byte>)output).Invoke((ReadOnlySpan<byte>)output2.Slice(0, producedBytes)); chars = chars.Slice(consumedChars); } while (reservedBufferSize != -1); } [SkipLocalsInit] private unsafe void CopyAndDecodeFromUtf16<TConsumer>([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, TConsumer output) where TConsumer : IReadOnlySpanConsumer<byte> { int num = reservedBufferSize + chars.Length; MemoryRental<char> memoryRental; if ((uint)num > (uint)MemoryRental<char>.StackallocThreshold) memoryRental = new MemoryRental<char>(num, true); else { int num2 = num; memoryRental = new Span<char>((void*)stackalloc byte[(int)checked(unchecked((ulong)(uint)num2) * 2)], num2); } MemoryRental<char> memoryRental2 = memoryRental; try { AsChars(ref reservedBuffer, reservedBufferSize).CopyTo(memoryRental2.Span); chars.CopyTo(memoryRental2.Span.Slice(reservedBufferSize)); DecodeFromUtf16Core(memoryRental2.Span, output); } finally { memoryRental2.Dispose(); } } [System.Runtime.CompilerServices.NullableContext(1)] public void DecodeFromUtf16<TConsumer>([LifetimeAnnotation(false, true)] [System.Runtime.CompilerServices.Nullable(0)] ReadOnlySpan<char> chars, TConsumer output) where TConsumer : IReadOnlySpanConsumer<byte> { switch (reservedBufferSize) { case -1: throw new FormatException(ExceptionMessages.MalformedBase64); case 0: DecodeFromUtf16Core(chars, output); break; default: CopyAndDecodeFromUtf16(chars, output); break; } } [System.Runtime.CompilerServices.NullableContext(1)] public void DecodeFromUtf16<[System.Runtime.CompilerServices.Nullable(2)] TArg>([LifetimeAnnotation(false, true)] [System.Runtime.CompilerServices.Nullable(0)] ReadOnlySpan<char> chars, ReadOnlySpanAction<byte, TArg> callback, TArg arg) { DecodeFromUtf16(chars, new DelegatingReadOnlySpanConsumer<byte, TArg>(callback, arg)); } [CLSCompliant(false)] public void DecodeFromUtf16<[System.Runtime.CompilerServices.Nullable(2)] TArg>([LifetimeAnnotation(false, true)] ReadOnlySpan<char> chars, [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 0, 1 })] IntPtr callback, [System.Runtime.CompilerServices.Nullable(1)] TArg arg) { DecodeFromUtf16(chars, new ReadOnlySpanConsumer<byte, TArg>(callback, arg)); } [System.Runtime.CompilerServices.NullableContext(2)] [AsyncIteratorStateMachine(typeof(<DecodeFromUtf16Async>d__21))] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0 })] public static IAsyncEnumerable<ReadOnlyMemory<byte>> DecodeFromUtf16Async([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0 })] IAsyncEnumerable<ReadOnlyMemory<char>> chars, MemoryAllocator<byte> allocator = null, [EnumeratorCancellation] CancellationToken token = default(CancellationToken)) { <DecodeFromUtf16Async>d__21 <DecodeFromUtf16Async>d__ = new <DecodeFromUtf16Async>d__21(-2); <DecodeFromUtf16Async>d__.<>3__chars = chars; <DecodeFromUtf16Async>d__.<>3__allocator = allocator; <DecodeFromUtf16Async>d__.<>3__token = token; return <DecodeFromUtf16Async>d__; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ReadOnlySpan<byte> AsReadOnlyBytes([In] [IsReadOnly] ref ulong value, int length) { return MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As<ulong, byte>(ref Unsafe.AsRef(ref value)), length); } private bool DecodeFromUtf8Core<TWriter>([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, [LifetimeAnnotation(true, false)] ref TWriter writer) where TWriter : IBufferWriter<byte> { int bytesWritten = Base64.GetMaxDecodedFromUtf8Length(utf8Chars.Length); Span<byte> span = ((IBufferWriter<byte>)writer).GetSpan(bytesWritten); int bytesConsumed; switch (Base64.DecodeFromUtf8(utf8Chars, span, out bytesConsumed, out bytesWritten, (utf8Chars.Length & 3) == 0)) { default: return false; case OperationStatus.Done: { int length = utf8Chars.Length; reservedBufferSize = ((length >= 1 && utf8Chars[length - 1] == 61) ? (-1) : 0); break; } case OperationStatus.DestinationTooSmall: reservedBufferSize = 0; break; case OperationStatus.NeedMoreData: reservedBufferSize = utf8Chars.Length - bytesConsumed; utf8Chars.Slice(bytesConsumed).CopyTo(Span.AsBytes(ref reservedBuffer)); break; } ((IBufferWriter<byte>)writer).Advance(bytesWritten); return true; } [SkipLocalsInit] private unsafe bool CopyAndDecodeFromUtf8<TWriter>([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, [LifetimeAnnotation(true, false)] ref TWriter writer) where TWriter : IBufferWriter<byte> { int num = reservedBufferSize + utf8Chars.Length; MemoryRental<byte> memoryRental; if ((uint)num > (uint)MemoryRental<byte>.StackallocThreshold) memoryRental = new MemoryRental<byte>(num, true); else { int num2 = num; memoryRental = new Span<byte>((void*)stackalloc byte[(int)(uint)num2], num2); } MemoryRental<byte> memoryRental2 = memoryRental; try { AsReadOnlyBytes(ref reservedBuffer, reservedBufferSize).CopyTo(memoryRental2.Span); utf8Chars.CopyTo(memoryRental2.Span.Slice(reservedBufferSize)); return DecodeFromUtf8Core(memoryRental2.Span, ref writer); } finally { memoryRental2.Dispose(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool DecodeFromUtf8<TWriter>([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, [LifetimeAnnotation(true, false)] ref TWriter writer) where TWriter : IBufferWriter<byte> { switch (reservedBufferSize) { case -1: return false; case 0: return DecodeFromUtf8Core(utf8Chars, ref writer); default: return CopyAndDecodeFromUtf8(utf8Chars, ref writer); } } public void DecodeFromUtf8([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, [System.Runtime.CompilerServices.Nullable(1)] IBufferWriter<byte> output) { ArgumentNullException.ThrowIfNull((object)output, "output"); if (!DecodeFromUtf8(utf8Chars, ref output)) throw new FormatException(ExceptionMessages.MalformedBase64); } public void DecodeFromUtf8([In] [LifetimeAnnotation(true, false)] [IsReadOnly] ref ReadOnlySequence<byte> utf8Chars, [System.Runtime.CompilerServices.Nullable(1)] IBufferWriter<byte> output) { ArgumentNullException.ThrowIfNull((object)output, "output"); ReadOnlySequence<byte>.Enumerator enumerator = utf8Chars.GetEnumerator(); do { if (!enumerator.MoveNext()) return; } while (DecodeFromUtf8(enumerator.Current.Span, ref output)); throw new FormatException(ExceptionMessages.MalformedBase64); } public MemoryOwner<byte> DecodeFromUtf8([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, [System.Runtime.CompilerServices.Nullable(2)] MemoryAllocator<byte> allocator = null) { MemoryOwnerWrapper<byte> writer = new MemoryOwnerWrapper<byte>(allocator); if (utf8Chars.IsEmpty || DecodeFromUtf8(utf8Chars, ref writer)) return writer.Buffer; writer.Buffer.Dispose(); throw new FormatException(ExceptionMessages.MalformedBase64); } [SkipLocalsInit] private unsafe void DecodeFromUtf8Core<TConsumer>([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, TConsumer output) where TConsumer : IReadOnlySpanConsumer<byte> { Span<byte> bytes = new Span<byte>((void*)stackalloc byte[258], 258); do { int bytesConsumed; int bytesWritten; switch (Base64.DecodeFromUtf8(utf8Chars, bytes, out bytesConsumed, out bytesWritten, (utf8Chars.Length & 3) == 0)) { default: throw new FormatException(ExceptionMessages.MalformedBase64); case OperationStatus.Done: { int length = utf8Chars.Length; reservedBufferSize = ((length >= 1 && utf8Chars[length - 1] == 61) ? (-1) : 0); break; } case OperationStatus.DestinationTooSmall: reservedBufferSize = 0; break; case OperationStatus.NeedMoreData: reservedBufferSize = utf8Chars.Length - bytesConsumed; utf8Chars.Slice(bytesConsumed).CopyTo(Span.AsBytes(ref reservedBuffer)); break; } if (bytesWritten == 0 || bytesConsumed == 0) break; ((IReadOnlySpanConsumer<byte>)output).Invoke((ReadOnlySpan<byte>)bytes.Slice(0, bytesWritten)); utf8Chars = utf8Chars.Slice(bytesConsumed); } while (reservedBufferSize != -1); } [SkipLocalsInit] private unsafe void CopyAndDecodeFromUtf8<TConsumer>([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, TConsumer output) where TConsumer : IReadOnlySpanConsumer<byte> { int num = reservedBufferSize + utf8Chars.Length; MemoryRental<byte> memoryRental; if ((uint)num > (uint)MemoryRental<byte>.StackallocThreshold) memoryRental = new MemoryRental<byte>(num, true); else { int num2 = num; memoryRental = new Span<byte>((void*)stackalloc byte[(int)(uint)num2], num2); } MemoryRental<byte> memoryRental2 = memoryRental; try { AsReadOnlyBytes(ref reservedBuffer, reservedBufferSize).CopyTo(memoryRental2.Span); utf8Chars.CopyTo(memoryRental2.Span.Slice(reservedBufferSize)); DecodeFromUtf8Core(memoryRental2.Span, output); } finally { memoryRental2.Dispose(); } } [System.Runtime.CompilerServices.NullableContext(1)] public void DecodeFromUtf8<TConsumer>([LifetimeAnnotation(false, true)] [System.Runtime.CompilerServices.Nullable(0)] ReadOnlySpan<byte> utf8Chars, TConsumer output) where TConsumer : IReadOnlySpanConsumer<byte> { switch (reservedBufferSize) { case -1: throw new FormatException(ExceptionMessages.MalformedBase64); case 0: DecodeFromUtf8Core(utf8Chars, output); break; default: CopyAndDecodeFromUtf8(utf8Chars, output); break; } } [System.Runtime.CompilerServices.NullableContext(1)] public void DecodeFromUtf8<[System.Runtime.CompilerServices.Nullable(2)] TArg>([LifetimeAnnotation(false, true)] [System.Runtime.CompilerServices.Nullable(0)] ReadOnlySpan<byte> utf8Chars, ReadOnlySpanAction<byte, TArg> output, TArg arg) { DecodeFromUtf8(utf8Chars, new DelegatingReadOnlySpanConsumer<byte, TArg>(output, arg)); } [CLSCompliant(false)] public void DecodeFromUtf8<[System.Runtime.CompilerServices.Nullable(2)] TArg>([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 0, 1 })] IntPtr output, [System.Runtime.CompilerServices.Nullable(1)] TArg arg) { DecodeFromUtf8(utf8Chars, new ReadOnlySpanConsumer<byte, TArg>(output, arg)); } public void DecodeFromUtf8([LifetimeAnnotation(false, true)] ReadOnlySpan<byte> utf8Chars, [System.Runtime.CompilerServices.Nullable(1)] Stream output) { DecodeFromUtf8(utf8Chars, (StreamConsumer)output); } [System.Runtime.CompilerServices.NullableContext(2)] [AsyncIteratorStateMachine(typeof(<DecodeFromUtf8Async>d__36))] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0 })] public static IAsyncEnumerable<ReadOnlyMemory<byte>> DecodeFromUtf8Async([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0 })] IAsyncEnumerable<ReadOnlyMemory<byte>> utf8Chars, MemoryAllocator<byte> allocator = null, [EnumeratorCancellation] CancellationToken token = default(CancellationToken)) { <DecodeFromUtf8Async>d__36 <DecodeFromUtf8Async>d__ = new <DecodeFromUtf8Async>d__36(-2); <DecodeFromUtf8Async>d__.<>3__utf8Chars = utf8Chars; <DecodeFromUtf8Async>d__.<>3__allocator = allocator; <DecodeFromUtf8Async>d__.<>3__token = token; return <DecodeFromUtf8Async>d__; } } }