Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Add Span<T> Base64 conversion APIs that support UTF-8 (#24888)
Browse files Browse the repository at this point in the history
* Add Span<T> Base64 conversion APIs that support UTF-8.

* Optimize the encoding loop when there is plenty of available space

* Optimize EncodeInPlace and update DecodeBaseline perf test.

* Addressing PR feedback, encode optimization, throw for negative lengths

* Reenable commented out perf tests.

* Cap the amount of data to process based on how much that will fit.

* Being explicit with access modifiers to follow guidelines.
  • Loading branch information
ahsonkhan authored Oct 27, 2017
1 parent dfb4bf4 commit b7b3439
Show file tree
Hide file tree
Showing 13 changed files with 1,813 additions and 7 deletions.
21 changes: 21 additions & 0 deletions src/System.Memory/ref/System.Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ public abstract class OwnedMemory<T> : IDisposable, IRetainable
public abstract void Retain();
protected internal abstract bool TryGetArray(out ArraySegment<T> arraySegment);
}

public enum OperationStatus
{
Done,
DestinationTooSmall,
NeedMoreData,
InvalidData,
}
}

namespace System.Buffers.Binary
Expand Down Expand Up @@ -277,4 +285,17 @@ public static class BinaryPrimitives
public static bool TryWriteUInt32BigEndian(Span<byte> buffer, uint value) { throw null; }
public static bool TryWriteUInt64BigEndian(Span<byte> buffer, ulong value) { throw null; }
}
}

namespace System.Buffers.Text
{
public static class Base64
{
public static OperationStatus EncodeToUtf8(ReadOnlySpan<byte> bytes, Span<byte> utf8, out int consumed, out int written, bool isFinalBlock = true) { throw null; }
public static OperationStatus EncodeToUtf8InPlace(Span<byte> buffer, int dataLength, out int written) { throw null; }
public static int GetMaxEncodedToUtf8Length(int length) { throw null; }
public static OperationStatus DecodeFromUtf8(ReadOnlySpan<byte> utf8, Span<byte> bytes, out int consumed, out int written, bool isFinalBlock = true) { throw null; }
public static OperationStatus DecodeFromUtf8InPlace(Span<byte> buffer, out int written) { throw null; }
public static int GetMaxDecodedFromUtf8Length(int length) { throw null; }
}
}
5 changes: 4 additions & 1 deletion src/System.Memory/src/System.Memory.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@
<Compile Include="System\SpanExtensions.cs" />
<Compile Include="System\SpanHelpers.T.cs" />
<Compile Include="System\SpanHelpers.byte.cs" />
<Compile Include="System\ThrowHelper.cs" />
<Compile Include="System\Buffers\OperationStatus.cs" />
<Compile Include="System\Buffers\Binary\Reader.cs" />
<Compile Include="System\Buffers\Binary\ReaderBigEndian.cs" />
<Compile Include="System\Buffers\Binary\ReaderLittleEndian.cs" />
<Compile Include="System\Buffers\Binary\Writer.cs" />
<Compile Include="System\Buffers\Binary\WriterBigEndian.cs" />
<Compile Include="System\Buffers\Binary\WriterLittleEndian.cs" />
<Compile Include="System\Buffers\Text\Base64Decoder.cs" />
<Compile Include="System\Buffers\Text\Base64Encoder.cs" />
</ItemGroup>
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
<Compile Include="System\ReadOnlySpan.cs" />
Expand All @@ -39,7 +43,6 @@
<Compile Include="System\SpanExtensions.Portable.cs" />
<Compile Include="System\SpanHelpers.cs" />
<Compile Include="System\Pinnable.cs" />
<Compile Include="System\ThrowHelper.cs" />
<Compile Include="System\SpanHelpers.Clear.cs" />
<Compile Include="System\Memory.cs" />
<Compile Include="System\MemoryDebugView.cs" />
Expand Down
6 changes: 3 additions & 3 deletions src/System.Memory/src/System/Buffers/Binary/Reader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ public static T ReadMachineEndian<T>(ReadOnlySpan<byte> buffer)
#else
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, typeof(T)));
ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
}
#endif
if (Unsafe.SizeOf<T>() > buffer.Length)
{
throw new ArgumentOutOfRangeException();
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
}
return Unsafe.ReadUnaligned<T>(ref buffer.DangerousGetPinnableReference());
}
Expand All @@ -132,7 +132,7 @@ public static bool TryReadMachineEndian<T>(ReadOnlySpan<byte> buffer, out T valu
#else
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, typeof(T)));
ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
}
#endif
if (Unsafe.SizeOf<T>() > (uint)buffer.Length)
Expand Down
6 changes: 3 additions & 3 deletions src/System.Memory/src/System/Buffers/Binary/Writer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public static void WriteMachineEndian<T>(Span<byte> buffer, ref T value)
#else
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, typeof(T)));
ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
}
#endif
if ((uint)Unsafe.SizeOf<T>() > (uint)buffer.Length)
{
throw new ArgumentOutOfRangeException();
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
}
Unsafe.WriteUnaligned<T>(ref buffer.DangerousGetPinnableReference(), value);
}
Expand All @@ -50,7 +50,7 @@ public static bool TryWriteMachineEndian<T>(Span<byte> buffer, ref T value)
#else
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, typeof(T)));
ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
}
#endif
if (Unsafe.SizeOf<T>() > (uint)buffer.Length)
Expand Down
34 changes: 34 additions & 0 deletions src/System.Memory/src/System/Buffers/OperationStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Buffers
{
/// <summary>
/// This enum defines the various potential status that can be returned from Span-based operations
/// that support processing of input contained in multiple discontiguous buffers.
/// </summary>
public enum OperationStatus
{
/// <summary>
/// The entire input buffer has been processed and the operation is complete.
/// </summary>
Done,
/// <summary>
/// The input is partially processed, up to what could fit into the destination buffer.
/// The caller can enlarge the destination buffer, slice the buffers appropriately, and retry.
/// </summary>
DestinationTooSmall,
/// <summary>
/// The input is partially processed, up to the last valid chunk of the input that could be consumed.
/// The caller can stitch the remaining unprocessed input with more data, slice the buffers appropriately, and retry.
/// </summary>
NeedMoreData,
/// <summary>
/// The input contained invalid bytes which could not be processed. If the input is partially processed,
/// the destination contains the partial result. This guarantees that no additional data appended to the input
/// will make the invalid sequence valid.
/// </summary>
InvalidData,
}
}
Loading

0 comments on commit b7b3439

Please sign in to comment.