Пример #1
0
        /// <inheritdoc />
        public override async ValueTask <decimal> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(4 *sizeof(short), async);

            var result = new DecimalRaw();
            var groups = buf.ReadInt16();
            var weight = buf.ReadInt16() - groups + 1;
            var sign   = buf.ReadUInt16();

            if ((sign & SignSpecialMask) == SignSpecialMask)
            {
                throw sign switch
                      {
                          SignNan => new InvalidCastException("Numeric NaN not supported by System.Decimal"),
                          SignPinf => new InvalidCastException("Numeric Infinity not supported by System.Decimal"),
                          SignNinf => new InvalidCastException("Numeric -Infinity not supported by System.Decimal"),
                          _ => new InvalidCastException($"Numeric special value {sign} not supported by System.Decimal")
                      };
            }

            if (sign == SignNegative)
            {
                DecimalRaw.Negate(ref result);
            }

            var scale = buf.ReadInt16();

            if (scale < 0 is var exponential && exponential)
            {
                scale = (short)(-scale);
            }
            else
            {
                result.Scale = scale;
            }

            if (scale > MaxDecimalScale)
            {
                throw new OverflowException("Numeric value does not fit in a System.Decimal");
            }

            var scaleDifference = exponential
                ? weight * MaxGroupScale
                : weight * MaxGroupScale + scale;

            if (groups > MaxGroupCount)
            {
                throw new OverflowException("Numeric value does not fit in a System.Decimal");
            }

            await buf.Ensure(groups *sizeof(ushort), async);

            if (groups == MaxGroupCount)
            {
                while (groups-- > 1)
                {
                    DecimalRaw.Multiply(ref result, MaxGroupSize);
                    DecimalRaw.Add(ref result, buf.ReadUInt16());
                }

                var group     = buf.ReadUInt16();
                var groupSize = DecimalRaw.Powers10[-scaleDifference];
                if (group % groupSize != 0)
                {
                    throw new OverflowException("Numeric value does not fit in a System.Decimal");
                }

                DecimalRaw.Multiply(ref result, MaxGroupSize / groupSize);
                DecimalRaw.Add(ref result, group / groupSize);
            }
            else
            {
                while (groups-- > 0)
                {
                    DecimalRaw.Multiply(ref result, MaxGroupSize);
                    DecimalRaw.Add(ref result, buf.ReadUInt16());
                }

                if (scaleDifference < 0)
                {
                    DecimalRaw.Divide(ref result, DecimalRaw.Powers10[-scaleDifference]);
                }
                else
                {
                    while (scaleDifference > 0)
                    {
                        var scaleChunk = Math.Min(DecimalRaw.MaxUInt32Scale, scaleDifference);
                        DecimalRaw.Multiply(ref result, DecimalRaw.Powers10[scaleChunk]);
                        scaleDifference -= scaleChunk;
                    }
                }
            }

            return(result.Value);
        }
Пример #2
0
        public override async ValueTask <NpgsqlTsQuery> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null, CancellationToken cancellationToken = default)
        {
            await buf.Ensure(4, async, cancellationToken);

            var numTokens = buf.ReadInt32();

            if (numTokens == 0)
            {
                return(new NpgsqlTsQueryEmpty());
            }

            NpgsqlTsQuery?value = null;
            var           nodes = new Stack <Tuple <NpgsqlTsQuery, int> >();

            len -= 4;

            for (var tokenPos = 0; tokenPos < numTokens; tokenPos++)
            {
                await buf.Ensure(Math.Min(len, MaxSingleTokenBytes), async, cancellationToken);

                var readPos = buf.ReadPosition;

                var isOper = buf.ReadByte() == 2;
                if (isOper)
                {
                    var operKind = (NpgsqlTsQuery.NodeKind)buf.ReadByte();
                    if (operKind == NpgsqlTsQuery.NodeKind.Not)
                    {
                        var node = new NpgsqlTsQueryNot(null);
                        InsertInTree(node, nodes, ref value);
                        nodes.Push(new Tuple <NpgsqlTsQuery, int>(node, 0));
                    }
                    else
                    {
                        var node = operKind switch
                        {
                            NpgsqlTsQuery.NodeKind.And => (NpgsqlTsQuery) new NpgsqlTsQueryAnd(null, null),
                            NpgsqlTsQuery.NodeKind.Or => new NpgsqlTsQueryOr(null, null),
                            NpgsqlTsQuery.NodeKind.Phrase => new NpgsqlTsQueryFollowedBy(null, buf.ReadInt16(), null),
                            _ => throw new InvalidOperationException($"Internal Npgsql bug: unexpected value {operKind} of enum {nameof(NpgsqlTsQuery.NodeKind)}. Please file a bug.")
                        };

                        InsertInTree(node, nodes, ref value);

                        nodes.Push(new Tuple <NpgsqlTsQuery, int>(node, 2));
                        nodes.Push(new Tuple <NpgsqlTsQuery, int>(node, 1));
                    }
                }
                else
                {
                    var weight = (NpgsqlTsQueryLexeme.Weight)buf.ReadByte();
                    var prefix = buf.ReadByte() != 0;
                    var str    = buf.ReadNullTerminatedString();
                    InsertInTree(new NpgsqlTsQueryLexeme(str, weight, prefix), nodes, ref value);
                }

                len -= buf.ReadPosition - readPos;
            }

            if (nodes.Count != 0)
            {
                throw new InvalidOperationException("Internal Npgsql bug, please report.");
            }

            return(value !);
Пример #3
0
        /// <inheritdoc />
        public override decimal Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            var result = new DecimalRaw();
            var groups = buf.ReadInt16();
            var weight = buf.ReadInt16() - groups + 1;
            var sign   = buf.ReadUInt16();

            if (sign == SignNan)
            {
                throw new InvalidCastException("Numeric NaN not supported by System.Decimal");
            }

            if (sign == SignNegative)
            {
                DecimalRaw.Negate(ref result);
            }

            var scale = buf.ReadInt16();

            if (scale > MaxDecimalScale)
            {
                throw new OverflowException("Numeric value does not fit in a System.Decimal");
            }

            result.Scale = scale;

            var scaleDifference = scale + weight * MaxGroupScale;

            if (groups == MaxGroupCount)
            {
                while (groups-- > 1)
                {
                    DecimalRaw.Multiply(ref result, MaxGroupSize);
                    DecimalRaw.Add(ref result, buf.ReadUInt16());
                }

                var group     = buf.ReadUInt16();
                var groupSize = DecimalRaw.Powers10[-scaleDifference];
                if (group % groupSize != 0)
                {
                    throw new OverflowException("Numeric value does not fit in a System.Decimal");
                }

                DecimalRaw.Multiply(ref result, MaxGroupSize / groupSize);
                DecimalRaw.Add(ref result, group / groupSize);
            }
            else
            {
                while (groups-- > 0)
                {
                    DecimalRaw.Multiply(ref result, MaxGroupSize);
                    DecimalRaw.Add(ref result, buf.ReadUInt16());
                }

                if (scaleDifference < 0)
                {
                    DecimalRaw.Divide(ref result, DecimalRaw.Powers10[-scaleDifference]);
                }
                else
                {
                    while (scaleDifference > 0)
                    {
                        var scaleChunk = Math.Min(DecimalRaw.MaxUInt32Scale, scaleDifference);
                        DecimalRaw.Multiply(ref result, DecimalRaw.Powers10[scaleChunk]);
                        scaleDifference -= scaleChunk;
                    }
                }
            }
            return(result.Value);
        }
Пример #4
0
 /// <inheritdoc />
 public override short Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
 => buf.ReadInt16();
Пример #5
0
        BigInteger INpgsqlSimpleTypeHandler <BigInteger> .Read(NpgsqlReadBuffer buf, int len, FieldDescription fieldDescription)
        {
            var result = new BigInteger();
            var groups = buf.ReadInt16();
            var weight = buf.ReadInt16() - groups + 1;
            var sign   = buf.ReadUInt16();

            if (sign == SignNan)
            {
                throw new NpgsqlSafeReadException(new InvalidCastException("Numeric NaN not supported by System.Numerics.BigInteger"));
            }

            var scale = buf.ReadInt16();

            if (scale > 0)
            {
                throw new NpgsqlSafeReadException(new OverflowException("Numeric value does not fit in a System.Numerics.BigInteger"));
            }

            try
            {
                var scaleDifference = scale + weight * MaxGroupScale;
                if (groups == MaxGroupCount)
                {
                    while (groups-- > 1)
                    {
                        result = result * MaxGroupSize;
                        result = result + buf.ReadUInt16();
                    }

                    var group     = buf.ReadUInt16();
                    var groupSize = DecimalRaw.Powers10[-scaleDifference];
                    if (group % groupSize != 0)
                    {
                        throw new NpgsqlSafeReadException(new OverflowException("Numeric value does not fit in a System.Numerics.BigInteger"));
                    }

                    result = result * (MaxGroupSize / groupSize);
                    result = result + (group / groupSize);
                }
                else
                {
                    while (groups-- > 0)
                    {
                        result = result * MaxGroupSize;
                        result = result + buf.ReadUInt16();
                    }

                    if (scaleDifference < 0)
                    {
                        result = result / (BigInteger)Math.Pow(10, -scaleDifference);
                    }
                    else
                    {
                        while (scaleDifference > 0)
                        {
                            var scaleChunk = Math.Min(DecimalRaw.MaxUInt32Scale, scaleDifference);
                            result           = result * (BigInteger)Math.Pow(10, scaleChunk);
                            scaleDifference -= scaleChunk;
                        }
                    }
                }
            }
            catch (OverflowException e)
            {
                throw new NpgsqlSafeReadException(e);
            }

            if (sign == SignNegative)
            {
                result = result * -1;
            }

            return(result);
        }