(ctx *ReadContext)
| 122 | } |
| 123 | |
| 124 | func readDecimalParts(ctx *ReadContext) (int32, *big.Int) { |
| 125 | err := ctx.Err() |
| 126 | scale := ctx.buffer.ReadVarint32(err) |
| 127 | header := ctx.buffer.ReadVarUint64(err) |
| 128 | if ctx.HasError() { |
| 129 | return 0, nil |
| 130 | } |
| 131 | if (header & 1) == 0 { |
| 132 | return scale, big.NewInt(decodeDecimalZigZag64(header >> 1)) |
| 133 | } |
| 134 | |
| 135 | meta := header >> 1 |
| 136 | length := meta >> 1 |
| 137 | if length == 0 { |
| 138 | ctx.SetError(DeserializationErrorf("invalid decimal magnitude length %d", length)) |
| 139 | return 0, nil |
| 140 | } |
| 141 | if length > uint64(MaxInt) { |
| 142 | ctx.SetError(DeserializationErrorf("invalid decimal magnitude length %d", length)) |
| 143 | return 0, nil |
| 144 | } |
| 145 | magnitudeBytes := ctx.buffer.ReadBytes(int(length), err) |
| 146 | if ctx.HasError() { |
| 147 | return 0, nil |
| 148 | } |
| 149 | if magnitudeBytes[len(magnitudeBytes)-1] == 0 { |
| 150 | ctx.SetError(DeserializationError("non-canonical decimal magnitude bytes: trailing zero byte")) |
| 151 | return 0, nil |
| 152 | } |
| 153 | bigEndian := append([]byte(nil), magnitudeBytes...) |
| 154 | reverseBytes(bigEndian) |
| 155 | magnitude := new(big.Int).SetBytes(bigEndian) |
| 156 | if magnitude.Sign() == 0 { |
| 157 | ctx.SetError(DeserializationError("big decimal encoding must not represent zero")) |
| 158 | return 0, nil |
| 159 | } |
| 160 | if (meta & 1) != 0 { |
| 161 | magnitude.Neg(magnitude) |
| 162 | } |
| 163 | return scale, magnitude |
| 164 | } |
| 165 | |
| 166 | func canUseSmallDecimalEncoding(value *big.Int) bool { |
| 167 | if value == nil { |
no test coverage detected