package it.cavallium.dbengine.database.serialization; import io.netty.buffer.api.Buffer; import io.netty.buffer.api.BufferAllocator; import io.netty.buffer.api.Send; import it.cavallium.dbengine.database.LLUtils; import java.nio.charset.StandardCharsets; import org.jetbrains.annotations.NotNull; @SuppressWarnings("unused") public interface SerializerFixedBinaryLength extends Serializer { int getSerializedBinaryLength(); static SerializerFixedBinaryLength, Send> noop(int length) { return new SerializerFixedBinaryLength<>() { @Override public @NotNull Send deserialize(@NotNull Send serialized) { try (var buf = serialized.receive()) { if (buf.readableBytes() != getSerializedBinaryLength()) { throw new IllegalArgumentException( "Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to deserialize an element with " + buf.readableBytes() + " bytes instead"); } return buf.send(); } } @Override public @NotNull Send serialize(@NotNull Send deserialized) { try (Buffer buf = deserialized.receive()) { 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.send(); } } @Override public int getSerializedBinaryLength() { return length; } }; } static SerializerFixedBinaryLength> utf8(BufferAllocator allocator, int length) { return new SerializerFixedBinaryLength<>() { @Override public @NotNull String deserialize(@NotNull Send serializedToReceive) throws SerializationException { try (var serialized = serializedToReceive.receive()) { if (serialized.readableBytes() != getSerializedBinaryLength()) { throw new SerializationException( "Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to deserialize an element with " + serialized.readableBytes() + " bytes instead"); } var readerOffset = serialized.readerOffset(); return LLUtils.deserializeString(serialized.send(), readerOffset, length, StandardCharsets.UTF_8); } } @Override public @NotNull Send serialize(@NotNull String deserialized) throws SerializationException { // UTF-8 uses max. 3 bytes per char, so calculate the worst case. try (Buffer buf = allocator.allocate(LLUtils.utf8MaxBytes(deserialized))) { LLUtils.writeString(buf, deserialized, StandardCharsets.UTF_8); if (buf.readableBytes() != getSerializedBinaryLength()) { throw new SerializationException("Fixed serializer with " + getSerializedBinaryLength() + " bytes has tried to serialize an element with " + buf.readableBytes() + " bytes instead"); } return buf.send(); } } @Override public int getSerializedBinaryLength() { return length; } }; } static SerializerFixedBinaryLength> intSerializer(BufferAllocator allocator) { return new SerializerFixedBinaryLength<>() { @Override public @NotNull Integer deserialize(@NotNull Send serializedToReceive) { try (var serialized = serializedToReceive.receive()) { 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(); } } @Override public @NotNull Send serialize(@NotNull Integer deserialized) { try (Buffer buf = allocator.allocate(Integer.BYTES)) { return buf.writeInt(deserialized).send(); } } @Override public int getSerializedBinaryLength() { return Integer.BYTES; } }; } static SerializerFixedBinaryLength> longSerializer(BufferAllocator allocator) { return new SerializerFixedBinaryLength<>() { @Override public @NotNull Long deserialize(@NotNull Send serializedToReceive) { try (var serialized = serializedToReceive.receive()) { 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(); } } @Override public @NotNull Send serialize(@NotNull Long deserialized) { try (Buffer buf = allocator.allocate(Long.BYTES)) { return buf.writeLong(deserialized).send(); } } @Override public int getSerializedBinaryLength() { return Long.BYTES; } }; } }