Skip to content

Commit

Permalink
Apply feedbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
buyaa-n committed Jun 21, 2024
1 parent 96dea87 commit 60e785b
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using static System.Buffers.Text.Base64Helper;

namespace System.Buffers.Text
{
Expand Down Expand Up @@ -29,7 +30,7 @@ public static partial class Base64
/// or if the input is incomplete (i.e. not a multiple of 4) and <paramref name="isFinalBlock"/> is <see langword="true"/>.
/// </returns>
public static OperationStatus DecodeFromUtf8(ReadOnlySpan<byte> utf8, Span<byte> bytes, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = true) =>
Base64Helper.DecodeFrom(Base64Helper.s_base64ByteDecoder, utf8, bytes, out bytesConsumed, out bytesWritten, isFinalBlock, ignoreWhiteSpace: true);
DecodeFrom(default(Base64DecoderByte), utf8, bytes, out bytesConsumed, out bytesWritten, isFinalBlock, ignoreWhiteSpace: true);

/// <summary>
/// Returns the maximum length (in bytes) of the result if you were to decode base 64 encoded text within a byte span of size "length".
Expand Down Expand Up @@ -61,6 +62,6 @@ public static int GetMaxDecodedFromUtf8Length(int length)
/// hence can only be called once with all the data in the buffer.
/// </returns>
public static OperationStatus DecodeFromUtf8InPlace(Span<byte> buffer, out int bytesWritten) =>
Base64Helper.DecodeFromUtf8InPlace(Base64Helper.s_base64ByteDecoder, buffer, out bytesWritten, ignoreWhiteSpace: true);
Base64Helper.DecodeFromUtf8InPlace(default(Base64DecoderByte), buffer, out bytesWritten, ignoreWhiteSpace: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using static System.Buffers.Text.Base64Helper;

namespace System.Buffers.Text
{
Expand Down Expand Up @@ -32,7 +33,7 @@ public static partial class Base64
/// It does not return InvalidData since that is not possible for base64 encoding.
/// </returns>
public static OperationStatus EncodeToUtf8(ReadOnlySpan<byte> bytes, Span<byte> utf8, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = true) =>
Base64Helper.EncodeTo(Base64Helper.s_base64ByteEncoder, bytes, utf8, out bytesConsumed, out bytesWritten, isFinalBlock);
EncodeTo(default(Base64EncoderByte), bytes, utf8, out bytesConsumed, out bytesWritten, isFinalBlock);

/// <summary>
/// Returns the maximum length (in bytes) of the result if you were to encode binary data within a byte span of size "length".
Expand All @@ -43,7 +44,7 @@ public static OperationStatus EncodeToUtf8(ReadOnlySpan<byte> bytes, Span<byte>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetMaxEncodedToUtf8Length(int length)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)length, Base64Helper.MaximumEncodeLength);
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)length, MaximumEncodeLength);

return ((length + 2) / 3) * 4;
}
Expand All @@ -64,6 +65,6 @@ public static int GetMaxEncodedToUtf8Length(int length)
/// It does not return InvalidData since that is not possible for base 64 encoding.
/// </returns>
public static OperationStatus EncodeToUtf8InPlace(Span<byte> buffer, int dataLength, out int bytesWritten) =>
Base64Helper.EncodeToUtf8InPlace(Base64Helper.s_base64ByteEncoder, buffer, dataLength, out bytesWritten);
Base64Helper.EncodeToUtf8InPlace(default(Base64EncoderByte), buffer, dataLength, out bytesWritten);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if NETCOREAPP
#if NET
using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.X86;
using System.Runtime.Intrinsics;
Expand All @@ -14,10 +14,6 @@ namespace System.Buffers.Text
{
internal static partial class Base64Helper
{
#pragma warning disable CA1805 // Member 's_base64ByteDecoder' is explicitly initialized to its default value
internal static Base64DecoderByte s_base64ByteDecoder = default;
#pragma warning restore CA1805

internal static unsafe OperationStatus DecodeFrom<TBase64Decoder, T>(TBase64Decoder decoder, ReadOnlySpan<T> source, Span<byte> bytes,
out int bytesConsumed, out int bytesWritten, bool isFinalBlock, bool ignoreWhiteSpace)
where TBase64Decoder : IBase64Decoder<T>
Expand Down Expand Up @@ -50,7 +46,7 @@ internal static unsafe OperationStatus DecodeFrom<TBase64Decoder, T>(TBase64Deco
T* srcEnd = srcBytes + (uint)srcLength;
T* srcMax = srcBytes + (uint)maxSrcLength;

#if NETCOREAPP
#if NET
if (maxSrcLength >= 24)
{
T* end = srcMax - 88;
Expand Down Expand Up @@ -112,7 +108,7 @@ internal static unsafe OperationStatus DecodeFrom<TBase64Decoder, T>(TBase64Deco
// This should never overflow since destLength here is less than int.MaxValue / 4 * 3 (i.e. 1610612733)
// Therefore, (destLength / 3) * 4 will always be less than 2147483641
Debug.Assert(destLength < (int.MaxValue / 4 * 3));
#if NETCOREAPP
#if NET
(maxSrcLength, int remainder) = int.DivRem(destLength, 3);
maxSrcLength *= 4;
#else
Expand Down Expand Up @@ -643,13 +639,13 @@ private static OperationStatus DecodeWithWhiteSpaceFromUtf8InPlace<TBase64Decode
return status;
}

#if NETCOREAPP
#if NET
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[CompExactlyDependsOn(typeof(Avx512BW))]
[CompExactlyDependsOn(typeof(Avx512Vbmi))]
private static unsafe void Avx512Decode<TBase64Decoder, T>(TBase64Decoder decoder, ref T* srcBytes, ref byte* destBytes, T* srcEnd, int sourceLength, int destLength, T* srcStart, byte* destStart)
where TBase64Decoder : IBase64Decoder<T>
where T : unmanaged
where TBase64Decoder : IBase64Decoder<T>
where T : unmanaged
{
// Reference for VBMI implementation : https://github.com/WojciechMula/base64simd/tree/master/decode
// If we have AVX512 support, pick off 64 bytes at a time for as long as we can,
Expand Down Expand Up @@ -1243,20 +1239,15 @@ internal static bool IsWhiteSpace(int value)

public uint AdvSimdLutTwo3Uint1 => 0x1B1AFFFF;

public int GetMaxDecodedLength(int utf8Length) =>
#if NETCOREAPP
Base64.GetMaxDecodedFromUtf8Length(utf8Length);
#else
0;
#endif
public int GetMaxDecodedLength(int utf8Length) => Base64.GetMaxDecodedFromUtf8Length(utf8Length);

public bool IsInvalidLength(int bufferLength) => bufferLength % 4 != 0; // only decode input if it is a multiple of 4

public bool IsValidPadding(uint padChar) => padChar == EncodingPad;

public int SrcLength(bool _, int utf8Length) => utf8Length & ~0x3; // only decode input up to the closest multiple of 4.

#if NETCOREAPP
#if NET
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[CompExactlyDependsOn(typeof(AdvSimd.Arm64))]
[CompExactlyDependsOn(typeof(Ssse3))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if NETCOREAPP
#if NET
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.X86;
Expand All @@ -13,10 +13,6 @@ namespace System.Buffers.Text
{
internal static partial class Base64Helper
{
#pragma warning disable CA1805 // Member 's_base64ByteEncoder' is explicitly initialized to its default value
internal static Base64EncoderByte s_base64ByteEncoder = default;
#pragma warning restore CA1805

internal static unsafe OperationStatus EncodeTo<TBase64Encoder, T>(TBase64Encoder encoder, ReadOnlySpan<byte> source,
Span<T> destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = true)
where TBase64Encoder : IBase64Encoder<T>
Expand All @@ -41,7 +37,7 @@ internal static unsafe OperationStatus EncodeTo<TBase64Encoder, T>(TBase64Encode
byte* srcEnd = srcBytes + (uint)srcLength;
byte* srcMax = srcBytes + (uint)maxSrcLength;

#if NETCOREAPP
#if NET
if (maxSrcLength >= 16)
{
byte* end = srcMax - 64;
Expand Down Expand Up @@ -132,13 +128,13 @@ internal static unsafe OperationStatus EncodeTo<TBase64Encoder, T>(TBase64Encode
}
}

#if NETCOREAPP
#if NET
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[CompExactlyDependsOn(typeof(Avx512BW))]
[CompExactlyDependsOn(typeof(Avx512Vbmi))]
private static unsafe void Avx512Encode<TBase64Encoder, T>(TBase64Encoder encoder, ref byte* srcBytes, ref T* destBytes, byte* srcEnd, int sourceLength, int destLength, byte* srcStart, T* destStart)
where TBase64Encoder : IBase64Encoder<T>
where T : unmanaged
where TBase64Encoder : IBase64Encoder<T>
where T : unmanaged
{
// Reference for VBMI implementation : https://github.com/WojciechMula/base64simd/tree/master/encode
// If we have AVX512 support, pick off 48 bytes at a time for as long as we can.
Expand Down Expand Up @@ -664,7 +660,7 @@ private static unsafe uint Encode(byte* threeBytes, ref byte encodingMap)

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetMaxSrcLength(int srcLength, int destLength) =>
#if NETCOREAPP
#if NET
srcLength <= MaximumEncodeLength && destLength >= Base64.GetMaxEncodedToUtf8Length(srcLength) ?
srcLength : (destLength >> 2) * 3;
#else
Expand All @@ -674,7 +670,7 @@ public int GetMaxSrcLength(int srcLength, int destLength) =>
public uint GetInPlaceDestinationLength(int encodedLength, int _) => (uint)(encodedLength - 4);

public int GetMaxEncodedLength(int srcLength) =>
#if NETCOREAPP
#if NET
Base64.GetMaxEncodedToUtf8Length(srcLength);
#else
0;
Expand Down Expand Up @@ -734,7 +730,7 @@ public unsafe void EncodeTwoOptionallyPadOne(byte* twoBytes, byte* dest, ref byt
}
}

#if NETCOREAPP
#if NET
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void StoreVector512ToDestination(byte* dest, byte* destStart, int destLength, Vector512<byte> str)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System.Diagnostics;
using System.Runtime.CompilerServices;
#if NETCOREAPP
#if NET
using System.Runtime.Intrinsics;
#endif

Expand Down Expand Up @@ -82,7 +82,7 @@ internal interface IBase64Encoder<T> where T : unmanaged
unsafe void EncodeThreeAndWrite(byte* threeBytes, T* destination, ref byte encodingMap);
int IncrementPadTwo { get; }
int IncrementPadOne { get; }
#if NETCOREAPP
#if NET
unsafe void StoreVector512ToDestination(T* dest, T* destStart, int destLength, Vector512<byte> str);
unsafe void StoreVector256ToDestination(T* dest, T* destStart, int destLength, Vector256<byte> str);
unsafe void StoreVector128ToDestination(T* dest, T* destStart, int destLength, Vector128<byte> str);
Expand All @@ -109,7 +109,7 @@ internal interface IBase64Decoder<T> where T : unmanaged
int GetMaxDecodedLength(int sourceLength);
bool IsInvalidLength(int bufferLength);
bool IsValidPadding(uint padChar);
#if NETCOREAPP
#if NET
bool TryDecode128Core(
Vector128<byte> str,
Vector128<byte> hiNibbles,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@ namespace System.Buffers.Text
{
internal static partial class Base64Helper
{
#pragma warning disable CA1805 // Member 's_base64ByteEncoder' is explicitly initialized to its default value
internal static Base64ByteValidatable s_base64ByteValidatable = default;
internal static Base64CharValidatable s_base64CharValidatable = default;
#pragma warning restore CA1805

internal static bool IsValid<T, TBase64Validatable>(TBase64Validatable validatable, ReadOnlySpan<T> base64Text, out int decodedLength)
where TBase64Validatable : IBase64Validatable<T>
{
int length = 0, paddingCount = 0;

if (!base64Text.IsEmpty)
{
#if NETCOREAPP
#if NET
while (true)
{

Expand Down Expand Up @@ -128,7 +123,7 @@ internal static bool IsValid<T, TBase64Validatable>(TBase64Validatable validatab

internal interface IBase64Validatable<T>
{
#if NETCOREAPP
#if NET
int IndexOfAnyExcept(ReadOnlySpan<T> span);
#else
int DecodeValue(T value);
Expand All @@ -140,7 +135,7 @@ internal interface IBase64Validatable<T>

internal readonly struct Base64CharValidatable : IBase64Validatable<char>
{
#if NETCOREAPP
#if NET
private static readonly SearchValues<char> s_validBase64Chars = SearchValues.Create("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");

public int IndexOfAnyExcept(ReadOnlySpan<char> span) => span.IndexOfAnyExcept(s_validBase64Chars);
Expand All @@ -153,24 +148,24 @@ public int DecodeValue(char value)
return -2;
}

return s_base64ByteDecoder.DecodingMap[value];
return default(Base64DecoderByte).DecodingMap[value];
}
#endif
public bool IsWhiteSpace(char value) => Base64Helper.IsWhiteSpace(value);
public bool IsEncodingPad(char value) => value == EncodingPad;
public bool ValidateAndDecodeLength(int length, int paddingCount, out int decodedLength) =>
s_base64ByteValidatable.ValidateAndDecodeLength(length, paddingCount, out decodedLength);
default(Base64ByteValidatable).ValidateAndDecodeLength(length, paddingCount, out decodedLength);
}

internal readonly struct Base64ByteValidatable : IBase64Validatable<byte>
{
#if NETCOREAPP
private static readonly SearchValues<byte> s_validBase64Chars = SearchValues.Create(s_base64ByteEncoder.EncodingMap);
#if NET
private static readonly SearchValues<byte> s_validBase64Chars = SearchValues.Create(default(Base64EncoderByte).EncodingMap);

public int IndexOfAnyExcept(ReadOnlySpan<byte> span) => span.IndexOfAnyExcept(s_validBase64Chars);
#else
public int DecodeValue(byte value) =>
s_base64ByteDecoder.DecodingMap[value];
default(Base64DecoderByte).DecodingMap[value];
#endif
public bool IsWhiteSpace(byte value) => Base64Helper.IsWhiteSpace(value);
public bool IsEncodingPad(byte value) => value == EncodingPad;
Expand Down
Loading

0 comments on commit 60e785b

Please sign in to comment.