Skip to content

Commit

Permalink
feat: Add ByteBuffer serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
Chuckame committed Sep 20, 2024
1 parent 775d74a commit 842f9df
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
9 changes: 9 additions & 0 deletions api/avro4k-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,15 @@ public final class com/github/avrokotlin/avro4k/serializer/BigIntegerSerializer
public fun serializeGeneric (Lkotlinx/serialization/encoding/Encoder;Ljava/math/BigInteger;)V
}

public final class com/github/avrokotlin/avro4k/serializer/ByteBufferSerializer : com/github/avrokotlin/avro4k/serializer/AvroSerializer {
public static final field INSTANCE Lcom/github/avrokotlin/avro4k/serializer/ByteBufferSerializer;
public synthetic fun deserializeAvro (Lcom/github/avrokotlin/avro4k/AvroDecoder;)Ljava/lang/Object;
public fun deserializeAvro (Lcom/github/avrokotlin/avro4k/AvroDecoder;)Ljava/nio/ByteBuffer;
public fun getSchema (Lcom/github/avrokotlin/avro4k/serializer/SchemaSupplierContext;)Lorg/apache/avro/Schema;
public synthetic fun serializeAvro (Lcom/github/avrokotlin/avro4k/AvroEncoder;Ljava/lang/Object;)V
public fun serializeAvro (Lcom/github/avrokotlin/avro4k/AvroEncoder;Ljava/nio/ByteBuffer;)V
}

public final class com/github/avrokotlin/avro4k/serializer/ElementLocation {
public fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;I)V
public final fun component1 ()Lkotlinx/serialization/descriptors/SerialDescriptor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public val JavaStdLibSerializersModule: SerializersModule =
contextual(UUIDSerializer)
contextual(BigIntegerSerializer)
contextual(BigDecimalSerializer)
contextual(ByteBufferSerializer)
}

public object URLSerializer : KSerializer<URL> {
Expand Down Expand Up @@ -315,4 +316,31 @@ public object BigDecimalSerializer : AvroSerializer<BigDecimal>(BigDecimal::clas
get() {
return LogicalTypes.decimal(precision, scale)
}
}

/**
* Delegates the serialization of a [ByteBuffer] to [AvroEncoder.encodeBytes] and [AvroDecoder.decodeBytes] as all the compatible types
* for the current writer schema are specifically handled here.
*/
public object ByteBufferSerializer : AvroSerializer<ByteBuffer>(ByteBuffer::class.qualifiedName!!) {
override fun getSchema(context: SchemaSupplierContext): Schema {
return Schema.create(Schema.Type.BYTES)
}

override fun serializeAvro(
encoder: AvroEncoder,
value: ByteBuffer,
) {
if (value.hasArray() && value.arrayOffset() == 0 && value.array().size == value.remaining()) {
encoder.encodeBytes(value.array())
} else {
val bytes = ByteArray(value.remaining())
value.get(bytes)
encoder.encodeBytes(bytes)
}
}

override fun deserializeAvro(decoder: AvroDecoder): ByteBuffer {
return ByteBuffer.wrap(decoder.decodeBytes())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,41 @@ import com.github.avrokotlin.avro4k.record
import io.kotest.core.spec.style.StringSpec
import kotlinx.serialization.Serializable
import org.apache.avro.Schema
import java.nio.ByteBuffer

internal class BytesEncodingTest : StringSpec({
"support ByteBuffer as BYTES" {
AvroAssertions.assertThat<ByteBuffer>(ByteBuffer.wrap(byteArrayOf(1, 4, 9)))
.generatesSchema(Schema.create(Schema.Type.BYTES))
.isEncodedAs(byteArrayOf(1, 4, 9))
AvroAssertions.assertThat<ByteBuffer?>(ByteBuffer.wrap(byteArrayOf(1, 4, 9)))
.generatesSchema(Schema.create(Schema.Type.BYTES).nullable)
.isEncodedAs(byteArrayOf(1, 4, 9))
AvroAssertions.assertThat<ByteBuffer?>(null)
.generatesSchema(Schema.create(Schema.Type.BYTES).nullable)
.isEncodedAs(null)
}

"support ByteBuffer as FIXED" {
val fixedSchema = Schema.createFixed("fixed", null, null, 3)
AvroAssertions.assertThat<ByteBuffer>(ByteBuffer.wrap(byteArrayOf(1, 4, 9)))
.isEncodedAs(byteArrayOf(1, 4, 9), writerSchema = fixedSchema)
AvroAssertions.assertThat<ByteBuffer?>(ByteBuffer.wrap(byteArrayOf(1, 4, 9)))
.isEncodedAs(byteArrayOf(1, 4, 9), writerSchema = fixedSchema.nullable)
AvroAssertions.assertThat<ByteBuffer?>(null)
.isEncodedAs(null, writerSchema = fixedSchema.nullable)
}

"support ByteBuffer as STRING" {
val stringSchema = Schema.create(Schema.Type.STRING)
AvroAssertions.assertThat<ByteBuffer>(ByteBuffer.wrap("string".encodeToByteArray()))
.isEncodedAs("string", writerSchema = stringSchema)
AvroAssertions.assertThat<ByteBuffer?>(ByteBuffer.wrap("string".encodeToByteArray()))
.isEncodedAs("string", writerSchema = stringSchema.nullable)
AvroAssertions.assertThat<ByteBuffer?>(null)
.isEncodedAs(null, writerSchema = stringSchema.nullable)
}

"encode/decode nullable ByteArray to BYTES" {
AvroAssertions.assertThat(NullableByteArrayTest(byteArrayOf(1, 4, 9)))
.isEncodedAs(record(byteArrayOf(1, 4, 9)))
Expand Down

0 comments on commit 842f9df

Please sign in to comment.