Skip to content

Commit 55c64e0

Browse files
committed
Prefer Unsafe.BitCast over MemoryMarshal.Cast
1 parent 9e932c4 commit 55c64e0

File tree

4 files changed

+34
-25
lines changed

4 files changed

+34
-25
lines changed

src/libraries/Common/src/System/Text/ValueStringBuilder_1.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ public override string ToString()
9999

100100
if (typeof(TChar) == typeof(Utf8Char))
101101
{
102-
result = Encoding.UTF8.GetString(MemoryMarshal.Cast<TChar, byte>(slice));
102+
result = Encoding.UTF8.GetString(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(slice));
103103
}
104104
else
105105
{
106106
Debug.Assert(typeof(TChar) == typeof(Utf16Char));
107-
result = MemoryMarshal.Cast<TChar, char>(slice).ToString();
107+
result = Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(slice).ToString();
108108
}
109109

110110
Dispose();

src/libraries/System.Runtime.Numerics/src/System/Number.BigInteger.cs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -776,12 +776,12 @@ internal static bool TryFormatBigInteger<TChar>(BigInteger value, ReadOnlySpan<c
776776
{
777777
if (typeof(TChar) == typeof(Utf8Char))
778778
{
779-
spanSuccess = value._sign.TryFormat(MemoryMarshal.Cast<TChar, byte>(destination), out charsWritten, formatSpan, info);
779+
spanSuccess = value._sign.TryFormat(Unsafe.BitCast<Span<TChar>, Span<byte>>(destination), out charsWritten, formatSpan, info);
780780
}
781781
else
782782
{
783783
Debug.Assert(typeof(TChar) == typeof(Utf16Char));
784-
spanSuccess = value._sign.TryFormat(MemoryMarshal.Cast<TChar, char>(destination), out charsWritten, formatSpan, info);
784+
spanSuccess = value._sign.TryFormat(Unsafe.BitCast<Span<TChar>, Span<char>>(destination), out charsWritten, formatSpan, info);
785785
}
786786
return null;
787787
}
@@ -873,7 +873,7 @@ internal static bool TryFormatBigInteger<TChar>(BigInteger value, ReadOnlySpan<c
873873
{
874874
digits = digits,
875875
base1E9Value = base1E9Value,
876-
sNegative = MemoryMarshal.Cast<TChar, char>(sNegative),
876+
sNegative = Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(sNegative),
877877
};
878878

879879
strResult = string.Create(strLength, state, static (span, state) =>
@@ -922,7 +922,16 @@ internal static bool TryFormatBigInteger<TChar>(BigInteger value, ReadOnlySpan<c
922922
{
923923
charsWritten = 0;
924924
spanSuccess = false;
925-
strResult = vlb.AsSpan().ToString();
925+
926+
if (typeof(TChar) == typeof(Utf8Char))
927+
{
928+
strResult = Encoding.UTF8.GetString(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(vlb.AsSpan()));
929+
}
930+
else
931+
{
932+
Debug.Assert(typeof(TChar) == typeof(Utf16Char));
933+
strResult = Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(vlb.AsSpan()).ToString();
934+
}
926935
}
927936

928937
vlb.Dispose();
@@ -1250,12 +1259,12 @@ static virtual bool TryParseUnalignedBlock(ReadOnlySpan<TChar> input, out uint r
12501259
{
12511260
if (typeof(TChar) == typeof(Utf8Char))
12521261
{
1253-
return uint.TryParse(MemoryMarshal.Cast<TChar, byte>(input), TParser.BlockNumberStyle, null, out result);
1262+
return uint.TryParse(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(input), TParser.BlockNumberStyle, null, out result);
12541263
}
12551264
else
12561265
{
12571266
Debug.Assert(typeof(TChar) == typeof(Utf16Char));
1258-
return uint.TryParse(MemoryMarshal.Cast<TChar, char>(input), TParser.BlockNumberStyle, null, out result);
1267+
return uint.TryParse(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(input), TParser.BlockNumberStyle, null, out result);
12591268
}
12601269
}
12611270

@@ -1296,8 +1305,8 @@ static virtual bool TryParseWholeBlocks(ReadOnlySpan<TChar> input, Span<uint> de
12961305
public static bool TryParseWholeBlocks(ReadOnlySpan<TChar> input, Span<uint> destination)
12971306
{
12981307
if ((typeof(TChar) == typeof(Utf8Char))
1299-
? (Number.FromHexString(MemoryMarshal.Cast<TChar, byte>(input), MemoryMarshal.AsBytes(destination), out _, out _) != OperationStatus.Done)
1300-
: (Convert.FromHexString(MemoryMarshal.Cast<TChar, char>(input), MemoryMarshal.AsBytes(destination), out _, out _) != OperationStatus.Done))
1308+
? (Number.FromHexString(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(input), MemoryMarshal.AsBytes(destination), out _, out _) != OperationStatus.Done)
1309+
: (Convert.FromHexString(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(input), MemoryMarshal.AsBytes(destination), out _, out _) != OperationStatus.Done))
13011310
{
13021311
return false;
13031312
}

src/libraries/System.Runtime.Numerics/src/System/Number.Polyfill.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ internal static OperationStatus DecodeFromUtfChar<TChar>(ReadOnlySpan<TChar> spa
109109
where TChar : unmanaged, IUtfChar<TChar>
110110
{
111111
return (typeof(TChar) == typeof(Utf8Char))
112-
? Rune.DecodeFromUtf8(MemoryMarshal.Cast<TChar, byte>(span), out result, out elemsConsumed)
113-
: Rune.DecodeFromUtf16(MemoryMarshal.Cast<TChar, char>(span), out result, out elemsConsumed);
112+
? Rune.DecodeFromUtf8(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(span), out result, out elemsConsumed)
113+
: Rune.DecodeFromUtf16(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(span), out result, out elemsConsumed);
114114
}
115115

116116
internal static OperationStatus FromHexString(ReadOnlySpan<byte> utf8Text, Span<byte> destination, out int charsConsumed, out int bytesWritten)
@@ -164,16 +164,16 @@ internal static bool TryDecodeHexStringFromUtf8(ReadOnlySpan<byte> utf8Text, Spa
164164
if (BitConverter.IsLittleEndian && (Ssse3.IsSupported || AdvSimd.Arm64.IsSupported || PackedSimd.IsSupported) &&
165165
(utf8Text.Length >= Vector128<byte>.Count))
166166
{
167-
return TryDecodeFromUtf16_Vector128(utf8Text, destination, out bytesProcessed);
167+
return TryDecodeFromUtf8_Vector128(utf8Text, destination, out bytesProcessed);
168168
}
169169

170170
return TryDecodeHexStringFromUtf8_Scalar(utf8Text, destination, out bytesProcessed);
171171
}
172172

173-
internal static bool TryDecodeFromUtf16_Vector128(ReadOnlySpan<byte> utf8Text, Span<byte> destination, out int bytesProcessed)
173+
internal static bool TryDecodeFromUtf8_Vector128(ReadOnlySpan<byte> utf8Text, Span<byte> destination, out int bytesProcessed)
174174
{
175175
Debug.Assert(Ssse3.IsSupported || AdvSimd.Arm64.IsSupported || PackedSimd.IsSupported);
176-
Debug.Assert(utf8Text.Length <= destination.Length);
176+
Debug.Assert(utf8Text.Length <= (destination.Length * 2));
177177
Debug.Assert((utf8Text.Length % 2) == 0);
178178
Debug.Assert(utf8Text.Length >= Vector128<byte>.Count);
179179

@@ -272,8 +272,8 @@ internal static bool AllCharsInVectorAreAscii(Vector128<byte> vec)
272272

273273
internal static bool TryDecodeHexStringFromUtf8_Scalar(ReadOnlySpan<byte> utf8Text, Span<byte> destination, out int bytesProcessed)
274274
{
275-
Debug.Assert(utf8Text.Length % 2 == 0, "Un-even number of characters provided");
276-
Debug.Assert(utf8Text.Length / 2 == destination.Length, "Target buffer not right-sized for provided characters");
275+
Debug.Assert((utf8Text.Length % 2) == 0, "Un-even number of characters provided");
276+
Debug.Assert((utf8Text.Length / 2) == destination.Length, "Target buffer not right-sized for provided characters");
277277

278278
int i = 0;
279279
int j = 0;

src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,8 +2136,8 @@ private static bool TryParse<TChar>(ReadOnlySpan<TChar> text, NumberStyles style
21362136
ReadOnlySpan<TChar> slice = text.Slice(openBracket + 1, semicolon - openBracket - 1);
21372137

21382138
if ((typeof(TChar) == typeof(Utf8Char))
2139-
? !double.TryParse(MemoryMarshal.Cast<TChar, byte>(slice), style, provider, out double real)
2140-
: !double.TryParse(MemoryMarshal.Cast<TChar, char>(slice), style, provider, out real))
2139+
? !double.TryParse(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(slice), style, provider, out double real)
2140+
: !double.TryParse(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(slice), style, provider, out real))
21412141
{
21422142
result = default;
21432143
return false;
@@ -2156,8 +2156,8 @@ private static bool TryParse<TChar>(ReadOnlySpan<TChar> text, NumberStyles style
21562156
slice = text.Slice(semicolon + 1, closeBracket - semicolon - 1);
21572157

21582158
if ((typeof(TChar) == typeof(Utf8Char))
2159-
? !double.TryParse(MemoryMarshal.Cast<TChar, byte>(slice), style, provider, out double imaginary)
2160-
: !double.TryParse(MemoryMarshal.Cast<TChar, char>(slice), style, provider, out imaginary))
2159+
? !double.TryParse(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(slice), style, provider, out double imaginary)
2160+
: !double.TryParse(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(slice), style, provider, out imaginary))
21612161
{
21622162
result = default;
21632163
return false;
@@ -2244,8 +2244,8 @@ private bool TryFormat<TChar>(Span<TChar> destination, out int charsWritten, Rea
22442244
if (destination.Length >= 6)
22452245
{
22462246
if ((typeof(TChar) == typeof(Utf8Char))
2247-
? m_real.TryFormat(MemoryMarshal.Cast<TChar, byte>(destination.Slice(1)), out int realChars, format, provider)
2248-
: m_real.TryFormat(MemoryMarshal.Cast<TChar, char>(destination.Slice(1)), out realChars, format, provider))
2247+
? m_real.TryFormat(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(destination.Slice(1)), out int realChars, format, provider)
2248+
: m_real.TryFormat(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(destination.Slice(1)), out realChars, format, provider))
22492249
{
22502250
destination[0] = TChar.CastFrom('<');
22512251
destination = destination.Slice(1 + realChars); // + 1 for <
@@ -2254,8 +2254,8 @@ private bool TryFormat<TChar>(Span<TChar> destination, out int charsWritten, Rea
22542254
if (destination.Length >= 4)
22552255
{
22562256
if ((typeof(TChar) == typeof(Utf8Char))
2257-
? m_imaginary.TryFormat(MemoryMarshal.Cast<TChar, byte>(destination.Slice(2)), out int imaginaryChars, format, provider)
2258-
: m_imaginary.TryFormat(MemoryMarshal.Cast<TChar, char>(destination.Slice(2)), out imaginaryChars, format, provider))
2257+
? m_imaginary.TryFormat(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<byte>>(destination.Slice(2)), out int imaginaryChars, format, provider)
2258+
: m_imaginary.TryFormat(Unsafe.BitCast<ReadOnlySpan<TChar>, ReadOnlySpan<char>>(destination.Slice(2)), out imaginaryChars, format, provider))
22592259
{
22602260
// We have 1 more character for: >
22612261
if ((uint)(2 + imaginaryChars) < (uint)destination.Length)

0 commit comments

Comments
 (0)