|
| 1 | +using System.Buffers.Binary; |
1 | 2 | using System.Buffers.Text;
|
2 | 3 | using System.Data.Common;
|
3 | 4 | using System.Diagnostics;
|
@@ -294,9 +295,9 @@ internal void AppendSqlString(ByteBufferWriter writer, StatementPreparerOptions
|
294 | 295 | Memory<byte> memory => memory.Span,
|
295 | 296 | MySqlGeometry geometry => geometry.ValueSpan,
|
296 | 297 | MemoryStream memoryStream => memoryStream.TryGetBuffer(out var streamBuffer) ? streamBuffer.AsSpan() : memoryStream.ToArray().AsSpan(),
|
297 |
| - float[] floatArray => MemoryMarshal.AsBytes(floatArray.AsSpan()), |
298 |
| - Memory<float> memory => MemoryMarshal.AsBytes(memory.Span), |
299 |
| - ReadOnlyMemory<float> memory => MemoryMarshal.AsBytes(memory.Span), |
| 298 | + float[] floatArray => ConvertFloatsToBytes(floatArray.AsSpan()), |
| 299 | + Memory<float> memory => ConvertFloatsToBytes(memory.Span), |
| 300 | + ReadOnlyMemory<float> memory => ConvertFloatsToBytes(memory.Span), |
300 | 301 | _ => ((ReadOnlyMemory<byte>) Value).Span,
|
301 | 302 | };
|
302 | 303 |
|
@@ -729,26 +730,52 @@ private void AppendBinary(ByteBufferWriter writer, object value, StatementPrepar
|
729 | 730 | }
|
730 | 731 | else if (value is float floatValue)
|
731 | 732 | {
|
732 |
| - writer.Write(BitConverter.GetBytes(floatValue)); |
| 733 | +#if NET5_0_OR_GREATER |
| 734 | + Span<byte> bytes = stackalloc byte[4]; |
| 735 | + BinaryPrimitives.WriteSingleLittleEndian(bytes, floatValue); |
| 736 | + writer.Write(bytes); |
| 737 | +#else |
| 738 | + // convert float to bytes with correct endianness (MySQL uses little-endian) |
| 739 | + var bytes = BitConverter.GetBytes(floatValue); |
| 740 | + if (!BitConverter.IsLittleEndian) |
| 741 | + Array.Reverse(bytes); |
| 742 | + writer.Write(bytes); |
| 743 | +#endif |
733 | 744 | }
|
734 | 745 | else if (value is double doubleValue)
|
735 | 746 | {
|
736 |
| - writer.Write(unchecked((ulong) BitConverter.DoubleToInt64Bits(doubleValue))); |
| 747 | +#if NET5_0_OR_GREATER |
| 748 | + Span<byte> bytes = stackalloc byte[8]; |
| 749 | + BinaryPrimitives.WriteDoubleLittleEndian(bytes, doubleValue); |
| 750 | + writer.Write(bytes); |
| 751 | +#else |
| 752 | + if (BitConverter.IsLittleEndian) |
| 753 | + { |
| 754 | + writer.Write(unchecked((ulong) BitConverter.DoubleToInt64Bits(doubleValue))); |
| 755 | + } |
| 756 | + else |
| 757 | + { |
| 758 | + // convert double to bytes with correct endianness (MySQL uses little-endian) |
| 759 | + var bytes = BitConverter.GetBytes(doubleValue); |
| 760 | + Array.Reverse(bytes); |
| 761 | + writer.Write(bytes); |
| 762 | + } |
| 763 | +#endif |
737 | 764 | }
|
738 | 765 | else if (value is float[] floatArrayValue)
|
739 | 766 | {
|
740 | 767 | writer.WriteLengthEncodedInteger(unchecked((ulong) floatArrayValue.Length * 4));
|
741 |
| - writer.Write(MemoryMarshal.AsBytes(floatArrayValue.AsSpan())); |
| 768 | + writer.Write(ConvertFloatsToBytes(floatArrayValue.AsSpan())); |
742 | 769 | }
|
743 | 770 | else if (value is Memory<float> floatMemory)
|
744 | 771 | {
|
745 | 772 | writer.WriteLengthEncodedInteger(unchecked((ulong) floatMemory.Length * 4));
|
746 |
| - writer.Write(MemoryMarshal.AsBytes(floatMemory.Span)); |
| 773 | + writer.Write(ConvertFloatsToBytes(floatMemory.Span)); |
747 | 774 | }
|
748 | 775 | else if (value is ReadOnlyMemory<float> floatReadOnlyMemory)
|
749 | 776 | {
|
750 | 777 | writer.WriteLengthEncodedInteger(unchecked((ulong) floatReadOnlyMemory.Length * 4));
|
751 |
| - writer.Write(MemoryMarshal.AsBytes(floatReadOnlyMemory.Span)); |
| 778 | + writer.Write(ConvertFloatsToBytes(floatReadOnlyMemory.Span)); |
752 | 779 | }
|
753 | 780 | else if (value is decimal decimalValue)
|
754 | 781 | {
|
@@ -967,6 +994,32 @@ private static void WriteTime(ByteBufferWriter writer, TimeSpan timeSpan)
|
967 | 994 | }
|
968 | 995 | }
|
969 | 996 |
|
| 997 | + private static ReadOnlySpan<byte> ConvertFloatsToBytes(ReadOnlySpan<float> floats) |
| 998 | + { |
| 999 | + if (BitConverter.IsLittleEndian) |
| 1000 | + { |
| 1001 | + return MemoryMarshal.AsBytes(floats); |
| 1002 | + } |
| 1003 | + else |
| 1004 | + { |
| 1005 | + // for big-endian platforms, we need to convert each float individually |
| 1006 | + var bytes = new byte[floats.Length * 4]; |
| 1007 | + |
| 1008 | + for (var i = 0; i < floats.Length; i++) |
| 1009 | + { |
| 1010 | +#if NET5_0_OR_GREATER |
| 1011 | + BinaryPrimitives.WriteSingleLittleEndian(bytes.AsSpan(i * 4), floats[i]); |
| 1012 | +#else |
| 1013 | + var floatBytes = BitConverter.GetBytes(floats[i]); |
| 1014 | + Array.Reverse(floatBytes); |
| 1015 | + floatBytes.CopyTo(bytes, i * 4); |
| 1016 | +#endif |
| 1017 | + } |
| 1018 | + |
| 1019 | + return bytes; |
| 1020 | + } |
| 1021 | + } |
| 1022 | + |
970 | 1023 | private static ReadOnlySpan<byte> BinaryBytes => "_binary'"u8;
|
971 | 1024 |
|
972 | 1025 | private DbType m_dbType;
|
|
0 commit comments