Skip to content

Commit ff89368

Browse files
rootmedhatiwari
root
authored andcommitted
Add Big Endian Support for Float32 in BinaryVectorWriter.WriteToBytes<T>()
Signed-off-by: Medha Tiwari <[email protected]>
1 parent d6840c3 commit ff89368

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

src/MongoDB.Bson/Serialization/BinaryVectorReader.cs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
using System;
17+
using System.Buffers.Binary;
1718
using System.Collections.Generic;
1819
using System.Linq;
1920
using System.Runtime.InteropServices;
@@ -26,7 +27,6 @@ public static BinaryVector<TItem> ReadBinaryVector<TItem>(ReadOnlyMemory<byte> v
2627
where TItem : struct
2728
{
2829
var (items, padding, vectorDataType) = ReadBinaryVectorAsArray<TItem>(vectorData);
29-
3030
return CreateBinaryVector(items, padding, vectorDataType);
3131
}
3232

@@ -41,29 +41,38 @@ public static (TItem[] Items, byte Padding, BinaryVectorDataType VectorDataType)
4141
switch (vectorDataType)
4242
{
4343
case BinaryVectorDataType.Float32:
44-
4544
if ((vectorDataBytes.Span.Length & 3) != 0)
4645
{
4746
throw new FormatException("Data length of binary vector of type Float32 must be a multiple of 4 bytes.");
4847
}
4948

50-
if (BitConverter.IsLittleEndian)
49+
if (typeof(TItem) != typeof(float))
5150
{
52-
var singles = MemoryMarshal.Cast<byte, float>(vectorDataBytes.Span);
53-
items = (TItem[])(object)singles.ToArray();
51+
throw new NotSupportedException($"Expected float for Float32 vector type, but found {typeof(TItem)}.");
5452
}
55-
else
53+
54+
int count = vectorDataBytes.Length / 4;
55+
float[] floatArray = new float[count];
56+
57+
for (int i = 0; i < count; i++)
5658
{
57-
throw new NotSupportedException("Binary vector data is not supported on Big Endian architecture yet.");
59+
floatArray[i] = BitConverter.IsLittleEndian
60+
? MemoryMarshal.Read<float>(vectorDataBytes.Span.Slice(i * 4, 4))
61+
: BinaryPrimitives.ReadSingleBigEndian(vectorDataBytes.Span.Slice(i * 4, 4));
5862
}
63+
64+
items = (TItem[])(object)floatArray;
5965
break;
66+
6067
case BinaryVectorDataType.Int8:
6168
var itemsSpan = MemoryMarshal.Cast<byte, TItem>(vectorDataBytes.Span);
62-
items = (TItem[])(object)itemsSpan.ToArray();
69+
items = itemsSpan.ToArray();
6370
break;
71+
6472
case BinaryVectorDataType.PackedBit:
6573
items = (TItem[])(object)vectorDataBytes.ToArray();
6674
break;
75+
6776
default:
6877
throw new NotSupportedException($"Binary vector data type {vectorDataType} is not supported.");
6978
}

src/MongoDB.Bson/Serialization/BinaryVectorWriter.cs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
using System;
17+
using System.Buffers.Binary;
1718
using System.Runtime.InteropServices;
1819

1920
namespace MongoDB.Bson.Serialization
@@ -35,15 +36,42 @@ public static byte[] WriteToBytes<TItem>(BinaryVector<TItem> binaryVector)
3536
public static byte[] WriteToBytes<TItem>(ReadOnlySpan<TItem> vectorData, BinaryVectorDataType binaryVectorDataType, byte padding)
3637
where TItem : struct
3738
{
38-
if (!BitConverter.IsLittleEndian)
39+
if (BitConverter.IsLittleEndian)
3940
{
40-
throw new NotSupportedException("Binary vector data is not supported on Big Endian architecture yet.");
41+
var vectorDataBytes = MemoryMarshal.Cast<TItem, byte>(vectorData);
42+
byte[] result = [(byte)binaryVectorDataType, padding, .. vectorDataBytes];
43+
return result;
4144
}
4245

43-
var vectorDataBytes = MemoryMarshal.Cast<TItem, byte>(vectorData);
44-
byte[] result = [(byte)binaryVectorDataType, padding, .. vectorDataBytes];
46+
byte[] resultBytes;
47+
switch (binaryVectorDataType)
48+
{
49+
case BinaryVectorDataType.Float32:
50+
int length = vectorData.Length * sizeof(float);
51+
resultBytes = new byte[2 + length];
52+
resultBytes[0] = (byte)binaryVectorDataType;
53+
resultBytes[1] = padding;
54+
var floatSpan = MemoryMarshal.Cast<TItem, float>(vectorData);
55+
Span<byte> floatOutput = resultBytes.AsSpan(2);
56+
foreach (var value in floatSpan)
57+
{
58+
BinaryPrimitives.WriteSingleBigEndian(floatOutput, value);
59+
floatOutput = floatOutput.Slice(4);
60+
}
61+
return resultBytes;
62+
63+
case BinaryVectorDataType.Int8:
64+
case BinaryVectorDataType.PackedBit:
65+
var vectorDataBytes = MemoryMarshal.Cast<TItem, byte>(vectorData);
66+
resultBytes = new byte[2 + vectorDataBytes.Length];
67+
resultBytes[0] = (byte)binaryVectorDataType;
68+
resultBytes[1] = padding;
69+
vectorDataBytes.CopyTo(resultBytes.AsSpan(2));
70+
return resultBytes;
4571

46-
return result;
72+
default:
73+
throw new NotSupportedException($"Binary vector serialization is not supported for {binaryVectorDataType} on Big Endian architecture yet.");
74+
}
4775
}
4876
}
4977
}

0 commit comments

Comments
 (0)