static private bool TryWriteUniformNumberArray()

in Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs [1019:1197]


            static private bool TryWriteUniformNumberArray(
                JsonBinaryMemoryWriter arrayWriter,
                int byteCount,
                int valueLength,
                int itemCount)
            {
                if (arrayWriter == null) throw new ArgumentNullException(nameof(arrayWriter));
                if (byteCount <= 0) throw new ArgumentException($"Value must be greater than 0.", nameof(byteCount));
                if (valueLength <= 0) throw new ArgumentException($"Value must be greater than 0.", nameof(valueLength));

                // Uniform arrays only support 1 and 2-byte item count
                if (itemCount > ushort.MaxValue) return false;

                int floatCount = 0;
                long maxValue = long.MinValue;
                long minValue = long.MaxValue;
                List<Number64> numberValues = new List<Number64>(itemCount);

                ReadOnlySpan<byte> arrayBuffer = arrayWriter.BufferAsSpan.Slice(arrayWriter.Position + byteCount, valueLength);
                while (!arrayBuffer.IsEmpty)
                {
                    if (!TypeMarker.IsNumber(arrayBuffer[0]))
                    {
                        // We encountered a non-number value, so we bail out
                        return false;
                    }

                    if (JsonBinaryEncoding.TryGetNumberValue(
                        arrayBuffer,
                        uniformArrayInfo: null,
                        out Number64 value,
                        out int itemLength))
                    {
                        numberValues.Add(value);

                        if (value.IsInteger)
                        {
                            maxValue = Math.Max(maxValue, Number64.ToLong(value));
                            minValue = Math.Min(minValue, Number64.ToLong(value));
                        }
                        else
                        {
                            floatCount++;
                        }
                    }
                    else
                    {
                        throw new JsonUnexpectedTokenException();
                    }

                    arrayBuffer = arrayBuffer.Slice(itemLength);
                }

                // Assert(numberValues.Count == itemCount);
                // Assert(itemCount >= floatCount);

                byte itemTypeMarker;
                int itemSize;

                if (floatCount > 0)
                {
                    if (floatCount < itemCount)
                    {
                        // Not all items are floating-point values, we need to check for integer values that
                        // cannot be represented as floating-point values without losing precision.

                        long nMaxAbsValue = Math.Max(Math.Abs(minValue), Math.Abs(maxValue));
                        if (nMaxAbsValue > (1L << 53)) return false;
                    }

                    itemTypeMarker = TypeMarker.Float64;
                    itemSize = sizeof(double);
                }
                else
                {
                    if ((minValue >= 0) && (maxValue <= byte.MaxValue))
                    {
                        itemTypeMarker = TypeMarker.UInt8;
                        itemSize = sizeof(byte);
                    }
                    else if ((minValue >= sbyte.MinValue) && (maxValue <= sbyte.MaxValue))
                    {
                        itemTypeMarker = TypeMarker.Int8;
                        itemSize = sizeof(sbyte);
                    }
                    else if ((minValue >= short.MinValue) && (maxValue <= short.MaxValue))
                    {
                        itemTypeMarker = TypeMarker.Int16;
                        itemSize = sizeof(short);
                    }
                    else if ((minValue >= int.MinValue) && (maxValue <= int.MaxValue))
                    {
                        itemTypeMarker = TypeMarker.Int32;
                        itemSize = sizeof(int);
                    }
                    else
                    {
                        itemTypeMarker = TypeMarker.Int64;
                        itemSize = sizeof(long);
                    }
                }

                int newByteCount = 1 /* item TypeMarker */ + (itemCount <= byte.MaxValue ? 1 : 2) /* item count */;
                int newLength = 1 + newByteCount + (itemCount * itemSize);
                int oldLength = 1 + byteCount + valueLength;

                // Verify whether writing a uniform number array is beneficial
                if (newLength > oldLength)
                {
                    return false;
                }

                if (itemCount <= byte.MaxValue)
                {
                    arrayWriter.Write(TypeMarker.ArrNumC1);
                    arrayWriter.Write(itemTypeMarker);
                    arrayWriter.Write((byte)itemCount);
                }
                else
                {
                    arrayWriter.Write(TypeMarker.ArrNumC2);
                    arrayWriter.Write(itemTypeMarker);
                    arrayWriter.Write((short)itemCount);
                }

                // Write the uniform number array beginning at the start offset
                switch (itemTypeMarker)
                {
                    case TypeMarker.Int8:
                        foreach (Number64 value in numberValues)
                        {
                            arrayWriter.Write((sbyte)Number64.ToLong(value));
                        }
                        break;
                    case TypeMarker.UInt8:
                        foreach (Number64 value in numberValues)
                        {
                            arrayWriter.Write((byte)Number64.ToLong(value));
                        }
                        break;
                    case TypeMarker.Int16:
                        foreach (Number64 value in numberValues)
                        {
                            arrayWriter.Write((short)Number64.ToLong(value));
                        }
                        break;
                    case TypeMarker.Int32:
                        foreach (Number64 value in numberValues)
                        {
                            arrayWriter.Write((int)Number64.ToLong(value));
                        }
                        break;
                    case TypeMarker.Int64:
                        foreach (Number64 value in numberValues)
                        {
                            arrayWriter.Write(Number64.ToLong(value));
                        }
                        break;
                    case TypeMarker.Float16:
                        // Currently not supported
                        throw new InvalidOperationException();
                    case TypeMarker.Float32:
                        foreach (Number64 value in numberValues)
                        {
                            arrayWriter.Write((float)Number64.ToDouble(value));
                        }
                        break;
                    case TypeMarker.Float64:
                        foreach (Number64 value in numberValues)
                        {
                            arrayWriter.Write(Number64.ToDouble(value));
                        }
                        break;
                    default:
                        throw new InvalidOperationException();
                }

                return true;
            }