mirror of https://github.com/tikv/client-java.git
add other codec (#12)
This commit is contained in:
parent
168e169fb1
commit
def2e5767f
38
pom.xml
38
pom.xml
|
@ -13,7 +13,6 @@
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<protobuf.version>3.1.0</protobuf.version>
|
<protobuf.version>3.1.0</protobuf.version>
|
||||||
<junit.version>4.12</junit.version>
|
|
||||||
<log4j.version>1.2.17</log4j.version>
|
<log4j.version>1.2.17</log4j.version>
|
||||||
<slf4j.version>1.7.16</slf4j.version>
|
<slf4j.version>1.7.16</slf4j.version>
|
||||||
<grpc.version>1.7.0</grpc.version>
|
<grpc.version>1.7.0</grpc.version>
|
||||||
|
@ -23,7 +22,6 @@
|
||||||
<trove4j.version>3.0.1</trove4j.version>
|
<trove4j.version>3.0.1</trove4j.version>
|
||||||
<joda-time.version>2.9.9</joda-time.version>
|
<joda-time.version>2.9.9</joda-time.version>
|
||||||
<joda-convert.version>1.9.2</joda-convert.version>
|
<joda-convert.version>1.9.2</joda-convert.version>
|
||||||
<spark.version>2.3.2</spark.version>
|
|
||||||
<proto.folder>${basedir}/proto</proto.folder>
|
<proto.folder>${basedir}/proto</proto.folder>
|
||||||
<scala.binary.version>2.11</scala.binary.version>
|
<scala.binary.version>2.11</scala.binary.version>
|
||||||
<scala.version>2.11</scala.version>
|
<scala.version>2.11</scala.version>
|
||||||
|
@ -65,6 +63,22 @@
|
||||||
<version>${grpc.version}</version>
|
<version>${grpc.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>joda-time</groupId>
|
||||||
|
<artifactId>joda-time</artifactId>
|
||||||
|
<version>${joda-time.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.joda</groupId>
|
||||||
|
<artifactId>joda-convert</artifactId>
|
||||||
|
<version>${joda-convert.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/net.sf.trove4j/trove4j -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.trove4j</groupId>
|
||||||
|
<artifactId>trove4j</artifactId>
|
||||||
|
<version>${trove4j.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -248,26 +262,6 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<!-- Assembly Plug-in -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<version>3.1.0</version>
|
|
||||||
<configuration>
|
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>assemble-all</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<!--- Needs to shade Protobuf 3 since other projects might use other version -->
|
<!--- Needs to shade Protobuf 3 since other projects might use other version -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
|
|
@ -17,7 +17,11 @@ package org.tikv.codec;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
import gnu.trove.list.array.TIntArrayList;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.Date;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import org.joda.time.*;
|
||||||
import org.tikv.exception.InvalidCodecFormatException;
|
import org.tikv.exception.InvalidCodecFormatException;
|
||||||
|
|
||||||
public class Codec {
|
public class Codec {
|
||||||
|
@ -315,4 +319,338 @@ public class Codec {
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class RealCodec {
|
||||||
|
|
||||||
|
private static final long signMask = 0x8000000000000000L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode as float
|
||||||
|
*
|
||||||
|
* @param cdi source of data
|
||||||
|
* @return decoded unsigned long value
|
||||||
|
*/
|
||||||
|
public static double readDouble(CodecDataInput cdi) {
|
||||||
|
long u = IntegerCodec.readULong(cdi);
|
||||||
|
if (u < 0) {
|
||||||
|
u &= Long.MAX_VALUE;
|
||||||
|
} else {
|
||||||
|
u = ~u;
|
||||||
|
}
|
||||||
|
return Double.longBitsToDouble(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long encodeDoubleToCmpLong(double val) {
|
||||||
|
long u = Double.doubleToRawLongBits(val);
|
||||||
|
if (val >= 0) {
|
||||||
|
u |= signMask;
|
||||||
|
} else {
|
||||||
|
u = ~u;
|
||||||
|
}
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeDoubleFully(CodecDataOutput cdo, double val) {
|
||||||
|
cdo.writeByte(FLOATING_FLAG);
|
||||||
|
writeDouble(cdo, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding a double value to byte buffer
|
||||||
|
*
|
||||||
|
* @param cdo For outputting data in bytes array
|
||||||
|
* @param val The data to encode
|
||||||
|
*/
|
||||||
|
public static void writeDouble(CodecDataOutput cdo, double val) {
|
||||||
|
IntegerCodec.writeULong(cdo, encodeDoubleToCmpLong(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DecimalCodec {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read a decimal value from CodecDataInput
|
||||||
|
*
|
||||||
|
* @param cdi cdi is source data.
|
||||||
|
*/
|
||||||
|
public static BigDecimal readDecimal(CodecDataInput cdi) {
|
||||||
|
if (cdi.available() < 3) {
|
||||||
|
throw new IllegalArgumentException("insufficient bytes to read value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 64 should be larger enough for avoiding unnecessary growth.
|
||||||
|
TIntArrayList data = new TIntArrayList(64);
|
||||||
|
int precision = cdi.readUnsignedByte();
|
||||||
|
int frac = cdi.readUnsignedByte();
|
||||||
|
int length = precision + frac;
|
||||||
|
int curPos = cdi.size() - cdi.available();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (cdi.eof()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data.add(cdi.readUnsignedByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
MyDecimal dec = new MyDecimal();
|
||||||
|
int binSize = dec.fromBin(precision, frac, data.toArray());
|
||||||
|
cdi.mark(curPos + binSize);
|
||||||
|
cdi.reset();
|
||||||
|
return dec.toDecimal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write a decimal value from CodecDataInput
|
||||||
|
*
|
||||||
|
* @param cdo cdo is destination data.
|
||||||
|
* @param dec is decimal value that will be written into cdo.
|
||||||
|
*/
|
||||||
|
static void writeDecimal(CodecDataOutput cdo, MyDecimal dec) {
|
||||||
|
int[] data = dec.toBin(dec.precision(), dec.frac());
|
||||||
|
cdo.writeByte(dec.precision());
|
||||||
|
cdo.writeByte(dec.frac());
|
||||||
|
for (int aData : data) {
|
||||||
|
cdo.writeByte(aData & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeDecimalFully(CodecDataOutput cdo, BigDecimal val) {
|
||||||
|
cdo.writeByte(DECIMAL_FLAG);
|
||||||
|
writeDecimal(cdo, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding a double value to byte buffer
|
||||||
|
*
|
||||||
|
* @param cdo For outputting data in bytes array
|
||||||
|
* @param val The data to encode
|
||||||
|
*/
|
||||||
|
public static void writeDecimal(CodecDataOutput cdo, BigDecimal val) {
|
||||||
|
MyDecimal dec = new MyDecimal();
|
||||||
|
dec.fromString(val.toPlainString());
|
||||||
|
writeDecimal(cdo, dec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DateTimeCodec {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a DateTime to a packed long converting to specific timezone
|
||||||
|
*
|
||||||
|
* @param dateTime dateTime that need to be encoded.
|
||||||
|
* @param tz timezone used for converting to localDateTime
|
||||||
|
* @return a packed long.
|
||||||
|
*/
|
||||||
|
static long toPackedLong(DateTime dateTime, DateTimeZone tz) {
|
||||||
|
LocalDateTime localDateTime = dateTime.withZone(tz).toLocalDateTime();
|
||||||
|
return toPackedLong(
|
||||||
|
localDateTime.getYear(),
|
||||||
|
localDateTime.getMonthOfYear(),
|
||||||
|
localDateTime.getDayOfMonth(),
|
||||||
|
localDateTime.getHourOfDay(),
|
||||||
|
localDateTime.getMinuteOfHour(),
|
||||||
|
localDateTime.getSecondOfMinute(),
|
||||||
|
localDateTime.getMillisOfSecond() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a date/time parts to a packed long.
|
||||||
|
*
|
||||||
|
* @return a packed long.
|
||||||
|
*/
|
||||||
|
static long toPackedLong(
|
||||||
|
int year, int month, int day, int hour, int minute, int second, int micro) {
|
||||||
|
long ymd = (year * 13 + month) << 5 | day;
|
||||||
|
long hms = hour << 12 | minute << 6 | second;
|
||||||
|
return ((ymd << 17 | hms) << 24) | micro;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read datetime from packed Long which contains all parts of a datetime namely, year, month,
|
||||||
|
* day and hour, min and sec, millisec. The original representation does not indicate any
|
||||||
|
* timezone information In Timestamp type, it should be interpreted as UTC while in DateType it
|
||||||
|
* is interpreted as local timezone
|
||||||
|
*
|
||||||
|
* @param packed long value that packs date / time parts
|
||||||
|
* @param tz timezone to interpret datetime parts
|
||||||
|
* @return decoded DateTime using provided timezone
|
||||||
|
*/
|
||||||
|
static DateTime fromPackedLong(long packed, DateTimeZone tz) {
|
||||||
|
// TODO: As for JDBC behavior, it can be configured to "round" or "toNull"
|
||||||
|
// for now we didn't pass in session so we do a toNull behavior
|
||||||
|
if (packed == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
long ymdhms = packed >> 24;
|
||||||
|
long ymd = ymdhms >> 17;
|
||||||
|
int day = (int) (ymd & ((1 << 5) - 1));
|
||||||
|
long ym = ymd >> 5;
|
||||||
|
int month = (int) (ym % 13);
|
||||||
|
int year = (int) (ym / 13);
|
||||||
|
|
||||||
|
int hms = (int) (ymdhms & ((1 << 17) - 1));
|
||||||
|
int second = hms & ((1 << 6) - 1);
|
||||||
|
int minute = (hms >> 6) & ((1 << 6) - 1);
|
||||||
|
int hour = hms >> 12;
|
||||||
|
int microsec = (int) (packed % (1 << 24));
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new DateTime(year, month, day, hour, minute, second, microsec / 1000, tz);
|
||||||
|
} catch (IllegalInstantException e) {
|
||||||
|
LocalDateTime localDateTime =
|
||||||
|
new LocalDateTime(year, month, day, hour, minute, second, microsec / 1000);
|
||||||
|
DateTime dt = localDateTime.toLocalDate().toDateTimeAtStartOfDay(tz);
|
||||||
|
long millis = dt.getMillis() + localDateTime.toLocalTime().getMillisOfDay();
|
||||||
|
return new DateTime(millis, tz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode DateTime as packed long converting into specified timezone All timezone conversion
|
||||||
|
* should be done beforehand
|
||||||
|
*
|
||||||
|
* @param cdo encoding output
|
||||||
|
* @param dateTime value to encode
|
||||||
|
* @param tz timezone used to converting local time
|
||||||
|
*/
|
||||||
|
public static void writeDateTimeFully(CodecDataOutput cdo, DateTime dateTime, DateTimeZone tz) {
|
||||||
|
long val = DateTimeCodec.toPackedLong(dateTime, tz);
|
||||||
|
IntegerCodec.writeULongFully(cdo, val, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode DateTime as packed long converting into specified timezone All timezone conversion
|
||||||
|
* should be done beforehand The encoded value has no data type flag
|
||||||
|
*
|
||||||
|
* @param cdo encoding output
|
||||||
|
* @param dateTime value to encode
|
||||||
|
* @param tz timezone used to converting local time
|
||||||
|
*/
|
||||||
|
public static void writeDateTimeProto(CodecDataOutput cdo, DateTime dateTime, DateTimeZone tz) {
|
||||||
|
long val = DateTimeCodec.toPackedLong(dateTime, tz);
|
||||||
|
IntegerCodec.writeULong(cdo, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read datetime from packed Long encoded as unsigned var-len integer converting into specified
|
||||||
|
* timezone
|
||||||
|
*
|
||||||
|
* @see DateTimeCodec#fromPackedLong(long, DateTimeZone)
|
||||||
|
* @param cdi codec buffer input
|
||||||
|
* @param tz timezone to interpret datetime parts
|
||||||
|
* @return decoded DateTime using provided timezone
|
||||||
|
*/
|
||||||
|
public static DateTime readFromUVarInt(CodecDataInput cdi, DateTimeZone tz) {
|
||||||
|
return DateTimeCodec.fromPackedLong(IntegerCodec.readUVarLong(cdi), tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read datetime from packed Long as unsigned fixed-len integer
|
||||||
|
*
|
||||||
|
* @see DateTimeCodec#fromPackedLong(long, DateTimeZone)
|
||||||
|
* @param cdi codec buffer input
|
||||||
|
* @param tz timezone to interpret datetime parts
|
||||||
|
* @return decoded DateTime using provided timezone
|
||||||
|
*/
|
||||||
|
public static DateTime readFromUInt(CodecDataInput cdi, DateTimeZone tz) {
|
||||||
|
return DateTimeCodec.fromPackedLong(IntegerCodec.readULong(cdi), tz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DateCodec {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a UTC Date to a packed long converting to specific timezone
|
||||||
|
*
|
||||||
|
* @param date date that need to be encoded.
|
||||||
|
* @param tz timezone used for converting to localDate
|
||||||
|
* @return a packed long.
|
||||||
|
*/
|
||||||
|
static long toPackedLong(Date date, DateTimeZone tz) {
|
||||||
|
return toPackedLong(date.getTime(), tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long toPackedLong(long utcMillsTs, DateTimeZone tz) {
|
||||||
|
LocalDate date = new LocalDate(utcMillsTs, tz);
|
||||||
|
return toPackedLong(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long toPackedLong(LocalDate date) {
|
||||||
|
return Codec.DateCodec.toPackedLong(
|
||||||
|
date.getYear(), date.getMonthOfYear(), date.getDayOfMonth());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a date part to a packed long.
|
||||||
|
*
|
||||||
|
* @return a packed long.
|
||||||
|
*/
|
||||||
|
static long toPackedLong(int year, int month, int day) {
|
||||||
|
long ymd = (year * 13 + month) << 5 | day;
|
||||||
|
return ymd << 41;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LocalDate fromPackedLong(long packed) {
|
||||||
|
// TODO: As for JDBC behavior, it can be configured to "round" or "toNull"
|
||||||
|
// for now we didn't pass in session so we do a toNull behavior
|
||||||
|
if (packed == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
long ymd = packed >> 41;
|
||||||
|
int day = (int) (ymd & ((1 << 5) - 1));
|
||||||
|
long ym = ymd >> 5;
|
||||||
|
int month = (int) (ym % 13);
|
||||||
|
int year = (int) (ym / 13);
|
||||||
|
|
||||||
|
return new LocalDate(year, month, day, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode Date as packed long converting into specified timezone All timezone conversion should
|
||||||
|
* be done beforehand
|
||||||
|
*
|
||||||
|
* @param cdo encoding output
|
||||||
|
* @param date value to encode
|
||||||
|
* @param tz timezone used to converting local time
|
||||||
|
*/
|
||||||
|
public static void writeDateFully(CodecDataOutput cdo, Date date, DateTimeZone tz) {
|
||||||
|
long val = DateCodec.toPackedLong(date, tz);
|
||||||
|
IntegerCodec.writeULongFully(cdo, val, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode Date as packed long converting into specified timezone All timezone conversion should
|
||||||
|
* be done beforehand The encoded value has no data type flag
|
||||||
|
*
|
||||||
|
* @param cdo encoding output
|
||||||
|
* @param date value to encode
|
||||||
|
* @param tz timezone used to converting local time
|
||||||
|
*/
|
||||||
|
public static void writeDateProto(CodecDataOutput cdo, Date date, DateTimeZone tz) {
|
||||||
|
long val = DateCodec.toPackedLong(date, tz);
|
||||||
|
IntegerCodec.writeULong(cdo, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read date from packed Long encoded as unsigned var-len integer converting into specified
|
||||||
|
* timezone
|
||||||
|
*
|
||||||
|
* @see DateCodec#fromPackedLong(long)
|
||||||
|
* @param cdi codec buffer input
|
||||||
|
* @return decoded DateTime using provided timezone
|
||||||
|
*/
|
||||||
|
public static LocalDate readFromUVarInt(CodecDataInput cdi) {
|
||||||
|
return DateCodec.fromPackedLong(IntegerCodec.readUVarLong(cdi));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read date from packed Long as unsigned fixed-len integer
|
||||||
|
*
|
||||||
|
* @see DateCodec#fromPackedLong(long)
|
||||||
|
* @param cdi codec buffer input
|
||||||
|
* @return decoded DateTime using provided timezone
|
||||||
|
*/
|
||||||
|
public static LocalDate readFromUInt(CodecDataInput cdi) {
|
||||||
|
return DateCodec.fromPackedLong(IntegerCodec.readULong(cdi));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue