private static void ProcessDecimal()

in csharp/src/Drivers/Apache/Hive2/DecimalUtility.cs [127:191]


        private static void ProcessDecimal(ReadOnlySpan<byte> value, int precision, int scale, ParserState state, out byte sign, out ReadOnlySpan<byte> integerSpan, out ReadOnlySpan<byte> fractionalSpan, out int neededScale)
        {
            int int_length = 0;
            int frac_length = 0;
            int exponent = 0;

            if (state.IntegerStart != -1 && state.IntegerEnd != -1) int_length = state.IntegerEnd - state.IntegerStart + 1;
            if (state.FractionalStart != -1 && state.FractionalEnd != -1) frac_length = state.FractionalEnd - state.FractionalStart + 1;
            if (state.ExponentIndex != -1 && state.ExponentStart != -1 && state.ExponentEnd != -1 && state.ExponentEnd >= state.ExponentStart)
            {
                int expStart = state.ExpSignIndex != -1 ? state.ExpSignIndex : state.ExponentStart;
                int expLength = state.ExponentEnd - expStart + 1;
                ReadOnlySpan<byte> exponentSpan = value.Slice(expStart, expLength);
                if (!Utf8Parser.TryParse(exponentSpan, out exponent, out int _))
                {
                    throw new FormatException($"unable to parse exponent value '{Encoding.UTF8.GetString(exponentSpan)}'");
                }
            }
            integerSpan = int_length > 0 ? value.Slice(state.IntegerStart, state.IntegerEnd - state.IntegerStart + 1) : [];
            fractionalSpan = frac_length > 0 ? value.Slice(state.FractionalStart, state.FractionalEnd - state.FractionalStart + 1) : [];
            Span<byte> tempSignificant;
            if (exponent != 0)
            {
                tempSignificant = new byte[int_length + frac_length];
                if (int_length > 0) value.Slice(state.IntegerStart, state.IntegerEnd - state.IntegerStart + 1).CopyTo(tempSignificant.Slice(0));
                if (frac_length > 0) value.Slice(state.FractionalStart, state.FractionalEnd - state.FractionalStart + 1).CopyTo(tempSignificant.Slice(int_length));
                // Trim trailing zeros from combined string
                while (tempSignificant[tempSignificant.Length - 1] == AsciiZero)
                {
                    tempSignificant = tempSignificant.Slice(0, tempSignificant.Length - 1);
                }
                // Recalculate integer and fractional length
                if (exponent > 0)
                {
                    int_length = Math.Min(int_length + exponent, tempSignificant.Length);
                    frac_length = Math.Max(Math.Min(frac_length - exponent, tempSignificant.Length - int_length), 0);
                }
                else
                {
                    int_length = Math.Max(int_length + exponent, 0);
                    frac_length = Math.Max(Math.Min(frac_length - exponent, tempSignificant.Length - int_length), 0);
                }
                // Reset the integer and fractional span
                fractionalSpan = tempSignificant.Slice(int_length, frac_length);
                integerSpan = tempSignificant.Slice(0, int_length);
                // Trim leading zeros fron new integer span
                while (integerSpan.Length > 0 && integerSpan[0] == AsciiZero)
                {
                    integerSpan = integerSpan.Slice(1);
                    int_length -= 1;
                }
            }

            int neededPrecision = int_length + frac_length;
            neededScale = frac_length;
            if (neededPrecision > precision)
            {
                throw new OverflowException($"Decimal precision cannot be greater than that in the Arrow vector: {Encoding.UTF8.GetString(value)} has precision > {precision}");
            }
            if (neededScale > scale)
            {
                throw new OverflowException($"Decimal scale cannot be greater than that in the Arrow vector: {Encoding.UTF8.GetString(value)} has scale > {scale}");
            }
            sign = state.SignIndex != -1 ? value[state.SignIndex] : AsciiPlus;
        }