2021-02-02 19:40:37 +01:00
|
|
|
package it.cavallium.dbengine.database.serialization;
|
|
|
|
|
|
|
|
import com.google.common.primitives.Ints;
|
|
|
|
import com.google.common.primitives.Longs;
|
2021-04-30 19:15:04 +02:00
|
|
|
import io.netty.buffer.ByteBuf;
|
|
|
|
import io.netty.buffer.ByteBufUtil;
|
|
|
|
import io.netty.buffer.PooledByteBufAllocator;
|
|
|
|
import java.io.NotSerializableException;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
import org.apache.commons.lang3.SerializationException;
|
2021-02-02 19:40:37 +01:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
2021-02-03 14:37:02 +01:00
|
|
|
@SuppressWarnings("unused")
|
2021-02-02 19:40:37 +01:00
|
|
|
public interface SerializerFixedBinaryLength<A, B> extends Serializer<A, B> {
|
|
|
|
|
|
|
|
int getSerializedBinaryLength();
|
|
|
|
|
2021-04-30 19:15:04 +02:00
|
|
|
static SerializerFixedBinaryLength<ByteBuf, ByteBuf> noop(int length) {
|
2021-02-02 19:40:37 +01:00
|
|
|
return new SerializerFixedBinaryLength<>() {
|
|
|
|
@Override
|
2021-04-30 19:15:04 +02:00
|
|
|
public @NotNull ByteBuf deserialize(@NotNull ByteBuf serialized) {
|
|
|
|
try {
|
|
|
|
if (serialized.readableBytes() != getSerializedBinaryLength()) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
"Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to deserialize an element with "
|
|
|
|
+ serialized.readableBytes() + " bytes instead");
|
|
|
|
}
|
|
|
|
return serialized.retain();
|
|
|
|
} finally {
|
|
|
|
serialized.release();
|
|
|
|
}
|
2021-02-02 19:40:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-04-30 19:15:04 +02:00
|
|
|
public @NotNull ByteBuf serialize(@NotNull ByteBuf deserialized) {
|
|
|
|
ByteBuf buf = deserialized.retain();
|
|
|
|
if (buf.readableBytes() != getSerializedBinaryLength()) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
"Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to serialize an element with "
|
|
|
|
+ buf.readableBytes() + " bytes instead");
|
|
|
|
}
|
|
|
|
return buf;
|
2021-02-02 19:40:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getSerializedBinaryLength() {
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-04-30 19:15:04 +02:00
|
|
|
static SerializerFixedBinaryLength<String, ByteBuf> utf8(int length) {
|
2021-02-02 19:40:37 +01:00
|
|
|
return new SerializerFixedBinaryLength<>() {
|
|
|
|
@Override
|
2021-04-30 19:15:04 +02:00
|
|
|
public @NotNull String deserialize(@NotNull ByteBuf serialized) {
|
|
|
|
try {
|
|
|
|
if (serialized.readableBytes() != getSerializedBinaryLength()) {
|
|
|
|
throw new SerializationException(
|
|
|
|
"Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to deserialize an element with "
|
|
|
|
+ serialized.readableBytes() + " bytes instead");
|
|
|
|
}
|
|
|
|
return serialized.toString(StandardCharsets.UTF_8);
|
|
|
|
} finally {
|
|
|
|
serialized.release();
|
|
|
|
}
|
2021-02-02 19:40:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-04-30 19:15:04 +02:00
|
|
|
public @NotNull ByteBuf serialize(@NotNull String deserialized) {
|
|
|
|
// UTF-8 uses max. 3 bytes per char, so calculate the worst case.
|
|
|
|
ByteBuf buf = PooledByteBufAllocator.DEFAULT.directBuffer(ByteBufUtil.utf8MaxBytes(deserialized));
|
|
|
|
try {
|
|
|
|
ByteBufUtil.writeUtf8(buf, deserialized);
|
|
|
|
if (buf.readableBytes() != getSerializedBinaryLength()) {
|
2021-05-02 19:18:15 +02:00
|
|
|
throw new SerializationException("Fixed serializer with " + getSerializedBinaryLength()
|
|
|
|
+ " bytes has tried to serialize an element with "
|
2021-04-30 19:15:04 +02:00
|
|
|
+ buf.readableBytes() + " bytes instead");
|
|
|
|
}
|
|
|
|
return buf.retain();
|
|
|
|
} finally {
|
|
|
|
buf.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getSerializedBinaryLength() {
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static SerializerFixedBinaryLength<Integer, ByteBuf> intSerializer() {
|
|
|
|
return new SerializerFixedBinaryLength<>() {
|
|
|
|
@Override
|
|
|
|
public @NotNull Integer deserialize(@NotNull ByteBuf serialized) {
|
|
|
|
try {
|
|
|
|
if (serialized.readableBytes() != getSerializedBinaryLength()) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
"Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to deserialize an element with "
|
|
|
|
+ serialized.readableBytes() + " bytes instead");
|
|
|
|
}
|
|
|
|
return serialized.readInt();
|
|
|
|
} finally {
|
|
|
|
serialized.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public @NotNull ByteBuf serialize(@NotNull Integer deserialized) {
|
|
|
|
ByteBuf buf = PooledByteBufAllocator.DEFAULT.directBuffer(Integer.BYTES, Integer.BYTES);
|
|
|
|
return buf.writeInt(deserialized);
|
2021-02-02 19:40:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getSerializedBinaryLength() {
|
|
|
|
return Integer.BYTES;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-04-30 19:15:04 +02:00
|
|
|
static SerializerFixedBinaryLength<Long, ByteBuf> longSerializer() {
|
2021-02-02 19:40:37 +01:00
|
|
|
return new SerializerFixedBinaryLength<>() {
|
|
|
|
@Override
|
2021-04-30 19:15:04 +02:00
|
|
|
public @NotNull Long deserialize(@NotNull ByteBuf serialized) {
|
|
|
|
try {
|
|
|
|
if (serialized.readableBytes() != getSerializedBinaryLength()) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
"Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to deserialize an element with "
|
|
|
|
+ serialized.readableBytes() + " bytes instead");
|
|
|
|
}
|
|
|
|
return serialized.readLong();
|
|
|
|
} finally {
|
|
|
|
serialized.release();
|
|
|
|
}
|
2021-02-02 19:40:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-04-30 19:15:04 +02:00
|
|
|
public @NotNull ByteBuf serialize(@NotNull Long deserialized) {
|
|
|
|
ByteBuf buf = PooledByteBufAllocator.DEFAULT.directBuffer(Integer.BYTES, Integer.BYTES);
|
|
|
|
return buf.writeLong(deserialized);
|
2021-02-02 19:40:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getSerializedBinaryLength() {
|
|
|
|
return Long.BYTES;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|