Skip to content

Commit b8da414

Browse files
committed
Polishing
Rename BigDecimalUtils to NumericDecodeUtils and move it into codec package. Make class package-protected. Move decodeNumber method from AbstractNumericCodec to number. Reduce codec visibility. [#349][resolves #350]
1 parent 23f244d commit b8da414

File tree

4 files changed

+143
-136
lines changed

4 files changed

+143
-136
lines changed

src/main/java/io/r2dbc/postgresql/codec/AbstractNumericCodec.java

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,12 @@
2020
import io.r2dbc.postgresql.message.Format;
2121
import io.r2dbc.postgresql.type.PostgresqlObjectId;
2222
import io.r2dbc.postgresql.util.Assert;
23-
import io.r2dbc.postgresql.util.BigDecimalUtils;
24-
import io.r2dbc.postgresql.util.ByteBufUtils;
2523
import reactor.util.annotation.Nullable;
2624

27-
import java.math.BigDecimal;
2825
import java.util.EnumSet;
2926
import java.util.Set;
3027
import java.util.function.Function;
3128

32-
import static io.r2dbc.postgresql.message.Format.FORMAT_BINARY;
3329
import static io.r2dbc.postgresql.type.PostgresqlObjectId.FLOAT4;
3430
import static io.r2dbc.postgresql.type.PostgresqlObjectId.FLOAT8;
3531
import static io.r2dbc.postgresql.type.PostgresqlObjectId.INT2;
@@ -87,60 +83,10 @@ boolean doCanDecode(PostgresqlObjectId type, Format format) {
8783
* @return the decoded number
8884
*/
8985
T decodeNumber(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Format format, Class<T> expectedType, Function<Number, T> converter) {
90-
Number number = decodeNumber(buffer, dataType, format);
86+
Number number = NumericDecodeUtils.decodeNumber(buffer, dataType, format);
9187
return potentiallyConvert(number, expectedType, converter);
9288
}
9389

94-
/**
95-
* Decode {@code buffer} to {@link Number} according to {@link PostgresqlObjectId}.
96-
*
97-
* @param buffer the data buffer
98-
* @param dataType the well-known {@link PostgresqlObjectId type OID}
99-
* @param format the data type {@link Format}, text or binary
100-
* @return the decoded number
101-
*/
102-
private Number decodeNumber(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Format format) {
103-
Assert.requireNonNull(buffer, "byteBuf must not be null");
104-
105-
switch (dataType) {
106-
107-
case NUMERIC:
108-
if (format == FORMAT_BINARY) {
109-
return BigDecimalUtils.decodeBinary(buffer);
110-
}
111-
return new BigDecimal(ByteBufUtils.decode(buffer));
112-
113-
case INT2:
114-
if (FORMAT_BINARY == format) {
115-
return buffer.readShort();
116-
}
117-
return Short.parseShort(ByteBufUtils.decode(buffer));
118-
case INT4:
119-
case OID:
120-
if (FORMAT_BINARY == format) {
121-
return buffer.readInt();
122-
}
123-
return Integer.parseInt(ByteBufUtils.decode(buffer));
124-
case INT8:
125-
if (FORMAT_BINARY == format) {
126-
return buffer.readLong();
127-
}
128-
return Long.parseLong(ByteBufUtils.decode(buffer));
129-
case FLOAT4:
130-
if (FORMAT_BINARY == format) {
131-
return buffer.readFloat();
132-
}
133-
return Float.parseFloat(ByteBufUtils.decode(buffer));
134-
case FLOAT8:
135-
if (FORMAT_BINARY == format) {
136-
return buffer.readDouble();
137-
}
138-
return Double.parseDouble(ByteBufUtils.decode(buffer));
139-
default:
140-
throw new UnsupportedOperationException(String.format("Cannot decode value for type %s, format %s", dataType, format));
141-
}
142-
}
143-
14490
/**
14591
* Returns the {@link PostgresqlObjectId} for to identify whether this codec is the default codec.
14692
*

src/main/java/io/r2dbc/postgresql/codec/BigDecimalArrayCodec.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@
2222
import io.r2dbc.postgresql.message.Format;
2323
import io.r2dbc.postgresql.type.PostgresqlObjectId;
2424
import io.r2dbc.postgresql.util.Assert;
25-
import io.r2dbc.postgresql.util.BigDecimalUtils;
2625

2726
import java.math.BigDecimal;
2827
import java.util.function.Supplier;
2928

30-
public class BigDecimalArrayCodec extends AbstractArrayCodec<BigDecimal> {
29+
final class BigDecimalArrayCodec extends AbstractArrayCodec<BigDecimal> {
3130

3231
public BigDecimalArrayCodec(ByteBufAllocator byteBufAllocator) {
3332
super(byteBufAllocator, BigDecimal.class);
@@ -47,7 +46,7 @@ boolean doCanDecode(PostgresqlObjectId type, Format format) {
4746

4847
@Override
4948
BigDecimal doDecodeBinary(ByteBuf byteBuffer) {
50-
return BigDecimalUtils.decodeBinary(byteBuffer);
49+
return NumericDecodeUtils.decodeBinary(byteBuffer);
5150
}
5251

5352
@Override
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.r2dbc.postgresql.codec;
18+
19+
import io.netty.buffer.ByteBuf;
20+
import io.r2dbc.postgresql.message.Format;
21+
import io.r2dbc.postgresql.type.PostgresqlObjectId;
22+
import io.r2dbc.postgresql.util.Assert;
23+
import io.r2dbc.postgresql.util.ByteBufUtils;
24+
import reactor.util.annotation.Nullable;
25+
26+
import java.math.BigDecimal;
27+
28+
import static io.r2dbc.postgresql.message.Format.FORMAT_BINARY;
29+
30+
/**
31+
* Utility methods to decode a numeric value.
32+
*/
33+
final class NumericDecodeUtils {
34+
35+
private NumericDecodeUtils() {
36+
}
37+
38+
/**
39+
* Decode {@code buffer} to {@link Number} according to {@link PostgresqlObjectId}.
40+
*
41+
* @param buffer the data buffer
42+
* @param dataType the well-known {@link PostgresqlObjectId type OID}
43+
* @param format the data type {@link Format}, text or binary
44+
* @return the decoded number
45+
*/
46+
public static Number decodeNumber(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Format format) {
47+
48+
Assert.requireNonNull(buffer, "byteBuf must not be null");
49+
50+
switch (dataType) {
51+
52+
case NUMERIC:
53+
if (format == FORMAT_BINARY) {
54+
return decodeBinary(buffer);
55+
}
56+
return new BigDecimal(ByteBufUtils.decode(buffer));
57+
58+
case INT2:
59+
if (FORMAT_BINARY == format) {
60+
return buffer.readShort();
61+
}
62+
return Short.parseShort(ByteBufUtils.decode(buffer));
63+
case INT4:
64+
case OID:
65+
if (FORMAT_BINARY == format) {
66+
return buffer.readInt();
67+
}
68+
return Integer.parseInt(ByteBufUtils.decode(buffer));
69+
case INT8:
70+
if (FORMAT_BINARY == format) {
71+
return buffer.readLong();
72+
}
73+
return Long.parseLong(ByteBufUtils.decode(buffer));
74+
case FLOAT4:
75+
if (FORMAT_BINARY == format) {
76+
return buffer.readFloat();
77+
}
78+
return Float.parseFloat(ByteBufUtils.decode(buffer));
79+
case FLOAT8:
80+
if (FORMAT_BINARY == format) {
81+
return buffer.readDouble();
82+
}
83+
return Double.parseDouble(ByteBufUtils.decode(buffer));
84+
default:
85+
throw new UnsupportedOperationException(String.format("Cannot decode value for type %s, format %s", dataType, format));
86+
}
87+
}
88+
89+
public static BigDecimal decodeBinary(ByteBuf byteBuf) {
90+
91+
// extract values
92+
short numOfDigits = byteBuf.readShort();
93+
if (numOfDigits == 0) {
94+
return BigDecimal.ZERO;
95+
}
96+
short weight = byteBuf.readShort();
97+
short sign = byteBuf.readShort();
98+
short scale = byteBuf.readShort();
99+
short[] digits = new short[numOfDigits];
100+
for (short i = 0; i < numOfDigits; i++) {
101+
digits[i] = byteBuf.readShort();
102+
}
103+
104+
StringBuilder builder = new StringBuilder();
105+
// whole part
106+
builder.append(digits[0]);
107+
for (short i = 0; i < weight * 4; i++) {
108+
builder.append(0);
109+
}
110+
// decimal part
111+
if (scale > 0) {
112+
builder.append('.');
113+
for (short i = 0; i < scale; i++) {
114+
builder.append(0);
115+
}
116+
}
117+
118+
int expectedLength = builder.length();
119+
int baseOffset = Short.toString(digits[0]).length();
120+
121+
for (short i = 1; i < numOfDigits; i++) {
122+
weight--;
123+
String temp = Short.toString(digits[i]);
124+
int offset = baseOffset + 4 * i - temp.length();
125+
if (weight < 0) {
126+
offset++; // dot between whole and decimal parts
127+
}
128+
builder.replace(offset, offset + temp.length(), temp);
129+
}
130+
131+
builder.setLength(expectedLength); // remove zeros from the end
132+
133+
if (sign == 0) {
134+
return new BigDecimal(builder.toString());
135+
} else {
136+
return new BigDecimal("-" + builder.toString());
137+
}
138+
}
139+
140+
}

src/main/java/io/r2dbc/postgresql/util/BigDecimalUtils.java

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)