Avoid using MemoryMarshal.Cast<byte, _> on Android
This centralizes *all* uses of this API to a `SafeBitConverter` class which does the efficient thing except on Android, where we fall back to a safe pattern. Fixes #931 See also #748, which was a similar fix but only to two call sites.
This commit is contained in:
Родитель
0f8645619e
Коммит
4d76ac860c
|
@ -102,6 +102,9 @@
|
|||
<Compile Include="..\..\src\MessagePack.UnityClient\Assets\Scripts\MessagePack\SequenceReaderExtensions.cs">
|
||||
<Link>Code\SequenceReaderExtensions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\src\MessagePack.UnityClient\Assets\Scripts\MessagePack\SafeBitConverter.cs">
|
||||
<Link>Code\SafeBitConverter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\src\MessagePack.UnityClient\Assets\Scripts\MessagePack\MessagePackCode.cs">
|
||||
<Link>Code\MessagePackCode.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
@ -427,7 +427,7 @@ namespace MessagePack.Internal
|
|||
{
|
||||
if (span.Length >= 8)
|
||||
{
|
||||
key = MemoryMarshal.Cast<byte, ulong>(span)[0];
|
||||
key = SafeBitConverter.ToUInt64(span);
|
||||
span = span.Slice(8);
|
||||
}
|
||||
else
|
||||
|
@ -443,7 +443,7 @@ namespace MessagePack.Internal
|
|||
|
||||
case 2:
|
||||
{
|
||||
key = MemoryMarshal.Cast<byte, ushort>(span)[0];
|
||||
key = SafeBitConverter.ToUInt16(span);
|
||||
span = span.Slice(2);
|
||||
break;
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ namespace MessagePack.Internal
|
|||
case 3:
|
||||
{
|
||||
var a = span[0];
|
||||
var b = MemoryMarshal.Cast<byte, ushort>(span.Slice(1))[0];
|
||||
var b = SafeBitConverter.ToUInt16(span.Slice(1));
|
||||
key = a | (ulong)b << 8;
|
||||
span = span.Slice(3);
|
||||
break;
|
||||
|
@ -459,7 +459,7 @@ namespace MessagePack.Internal
|
|||
|
||||
case 4:
|
||||
{
|
||||
key = MemoryMarshal.Cast<byte, uint>(span)[0];
|
||||
key = SafeBitConverter.ToUInt32(span);
|
||||
span = span.Slice(4);
|
||||
break;
|
||||
}
|
||||
|
@ -467,7 +467,7 @@ namespace MessagePack.Internal
|
|||
case 5:
|
||||
{
|
||||
var a = span[0];
|
||||
var b = MemoryMarshal.Cast<byte, uint>(span.Slice(1))[0];
|
||||
var b = SafeBitConverter.ToUInt32(span.Slice(1));
|
||||
key = a | (ulong)b << 8;
|
||||
span = span.Slice(5);
|
||||
break;
|
||||
|
@ -475,8 +475,8 @@ namespace MessagePack.Internal
|
|||
|
||||
case 6:
|
||||
{
|
||||
ulong a = MemoryMarshal.Cast<byte, ushort>(span)[0];
|
||||
ulong b = MemoryMarshal.Cast<byte, uint>(span.Slice(2))[0];
|
||||
ulong a = SafeBitConverter.ToUInt16(span);
|
||||
ulong b = SafeBitConverter.ToUInt32(span.Slice(2));
|
||||
key = a | (b << 16);
|
||||
span = span.Slice(6);
|
||||
break;
|
||||
|
@ -485,8 +485,8 @@ namespace MessagePack.Internal
|
|||
case 7:
|
||||
{
|
||||
var a = span[0];
|
||||
var b = MemoryMarshal.Cast<byte, ushort>(span.Slice(1))[0];
|
||||
var c = MemoryMarshal.Cast<byte, uint>(span.Slice(3))[0];
|
||||
var b = SafeBitConverter.ToUInt16(span.Slice(1));
|
||||
var c = SafeBitConverter.ToUInt32(span.Slice(3));
|
||||
key = a | (ulong)b << 8 | (ulong)c << 24;
|
||||
span = span.Slice(7);
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
// Copyright (c) All contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MessagePack
|
||||
{
|
||||
internal static class SafeBitConverter
|
||||
{
|
||||
internal static long ToInt64(ReadOnlySpan<byte> value)
|
||||
{
|
||||
#if UNITY_ANDROID
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
int i1 = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
|
||||
int i2 = value[4] | (value[5] << 8) | (value[6] << 16) | (value[7] << 24);
|
||||
return (uint)i1 | ((long)i2 << 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
|
||||
int i2 = (value[4] << 24) | (value[5] << 16) | (value[6] << 8) | value[7];
|
||||
return (uint)i2 | ((long)i1 << 32);
|
||||
}
|
||||
#else
|
||||
return MemoryMarshal.Cast<byte, long>(value)[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static ulong ToUInt64(ReadOnlySpan<byte> value) => unchecked((ulong)ToInt64(value));
|
||||
|
||||
internal static ushort ToUInt16(ReadOnlySpan<byte> value)
|
||||
{
|
||||
#if UNITY_ANDROID
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
return (ushort)(value[0] | (value[1] << 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (ushort)((value[0] << 8) | value[1]);
|
||||
}
|
||||
#else
|
||||
return MemoryMarshal.Cast<byte, ushort>(value)[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static uint ToUInt32(ReadOnlySpan<byte> value)
|
||||
{
|
||||
#if UNITY_ANDROID
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
return (uint)(value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (uint)((value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3]);
|
||||
}
|
||||
#else
|
||||
return MemoryMarshal.Cast<byte, uint>(value)[0];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -58,27 +58,11 @@ namespace System.Buffers
|
|||
return TryReadMultisegment(ref reader, out value);
|
||||
}
|
||||
|
||||
value = BitConverterToInt64(span);
|
||||
value = SafeBitConverter.ToInt64(span);
|
||||
reader.Advance(sizeof(long));
|
||||
return true;
|
||||
}
|
||||
|
||||
private static unsafe long BitConverterToInt64(ReadOnlySpan<byte> value)
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
int i1 = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
|
||||
int i2 = value[4] | (value[5] << 8) | (value[6] << 16) | (value[7] << 24);
|
||||
return (uint)i1 | ((long)i2 << 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
|
||||
int i2 = (value[4] << 24) | (value[5] << 16) | (value[6] << 8) | value[7];
|
||||
return (uint)i2 | ((long)i1 << 32);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
private static unsafe bool TryReadMultisegment<T>(ref SequenceReader<byte> reader, out T value)
|
||||
|
@ -117,7 +101,7 @@ namespace System.Buffers
|
|||
return false;
|
||||
}
|
||||
|
||||
value = BitConverterToInt64(tempSpan);
|
||||
value = SafeBitConverter.ToInt64(tempSpan);
|
||||
reader.Advance(sizeof(long));
|
||||
return true;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче