2021-02-02 19:40:37 +01:00
|
|
|
package it.cavallium.dbengine.database.serialization;
|
|
|
|
|
|
|
|
import io.netty.buffer.ByteBuf;
|
2021-05-03 21:41:51 +02:00
|
|
|
import io.netty.buffer.ByteBufAllocator;
|
2021-02-02 19:40:37 +01:00
|
|
|
import io.netty.buffer.ByteBufInputStream;
|
|
|
|
import io.netty.buffer.ByteBufOutputStream;
|
2021-04-30 19:15:04 +02:00
|
|
|
import io.netty.buffer.PooledByteBufAllocator;
|
2021-02-02 19:40:37 +01:00
|
|
|
import io.netty.buffer.Unpooled;
|
2021-02-11 01:09:15 +01:00
|
|
|
import java.io.IOError;
|
2021-02-02 19:40:37 +01:00
|
|
|
import java.io.IOException;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.warp.commonutils.error.IndexOutOfBoundsException;
|
|
|
|
|
2021-04-30 19:15:04 +02:00
|
|
|
public class CodecSerializer<A> implements Serializer<A, ByteBuf> {
|
2021-02-02 19:40:37 +01:00
|
|
|
|
2021-05-03 21:41:51 +02:00
|
|
|
private final ByteBufAllocator allocator;
|
2021-02-02 19:40:37 +01:00
|
|
|
private final Codecs<A> deserializationCodecs;
|
|
|
|
private final Codec<A> serializationCodec;
|
|
|
|
private final int serializationCodecId;
|
|
|
|
private final boolean microCodecs;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param microCodecs if true, allow only codecs with a value from 0 to 255 to save disk space
|
|
|
|
*/
|
2021-05-03 21:41:51 +02:00
|
|
|
public CodecSerializer(
|
|
|
|
ByteBufAllocator allocator,
|
|
|
|
Codecs<A> deserializationCodecs,
|
2021-02-02 19:40:37 +01:00
|
|
|
Codec<A> serializationCodec,
|
|
|
|
int serializationCodecId,
|
|
|
|
boolean microCodecs) {
|
2021-05-03 21:41:51 +02:00
|
|
|
this.allocator = allocator;
|
2021-02-02 19:40:37 +01:00
|
|
|
this.deserializationCodecs = deserializationCodecs;
|
|
|
|
this.serializationCodec = serializationCodec;
|
|
|
|
this.serializationCodecId = serializationCodecId;
|
|
|
|
this.microCodecs = microCodecs;
|
|
|
|
if (microCodecs && (serializationCodecId > 255 || serializationCodecId < 0)) {
|
|
|
|
throw new IndexOutOfBoundsException(serializationCodecId, 0, 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-04-30 19:15:04 +02:00
|
|
|
public @NotNull A deserialize(@NotNull ByteBuf serialized) {
|
|
|
|
try (var is = new ByteBufInputStream(serialized)) {
|
2021-02-02 19:40:37 +01:00
|
|
|
int codecId;
|
|
|
|
if (microCodecs) {
|
|
|
|
codecId = is.readUnsignedByte();
|
|
|
|
} else {
|
|
|
|
codecId = is.readInt();
|
|
|
|
}
|
|
|
|
var serializer = deserializationCodecs.getCodec(codecId);
|
|
|
|
return serializer.deserialize(is);
|
|
|
|
} catch (IOException ex) {
|
|
|
|
// This shouldn't happen
|
2021-02-11 01:09:15 +01:00
|
|
|
throw new IOError(ex);
|
2021-04-30 19:15:04 +02:00
|
|
|
} 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 A deserialized) {
|
2021-05-03 21:41:51 +02:00
|
|
|
ByteBuf buf = allocator.buffer();
|
2021-02-02 19:40:37 +01:00
|
|
|
try (var os = new ByteBufOutputStream(buf)) {
|
|
|
|
if (microCodecs) {
|
|
|
|
os.writeByte(serializationCodecId);
|
|
|
|
} else {
|
|
|
|
os.writeInt(serializationCodecId);
|
|
|
|
}
|
|
|
|
serializationCodec.serialize(os, deserialized);
|
|
|
|
} catch (IOException ex) {
|
|
|
|
// This shouldn't happen
|
2021-02-11 01:09:15 +01:00
|
|
|
throw new IOError(ex);
|
|
|
|
}
|
2021-04-30 19:15:04 +02:00
|
|
|
return buf;
|
2021-02-11 01:09:15 +01:00
|
|
|
}
|
|
|
|
|
2021-04-03 19:09:06 +02:00
|
|
|
@SuppressWarnings("unused")
|
2021-02-11 01:09:15 +01:00
|
|
|
public int getCodecHeadersBytes() {
|
|
|
|
if (microCodecs) {
|
|
|
|
return Byte.BYTES;
|
|
|
|
} else {
|
|
|
|
return Integer.BYTES;
|
2021-02-02 19:40:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|