Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Improve documentation #210

Merged
merged 4 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,065 changes: 634 additions & 431 deletions README.md

Large diffs are not rendered by default.

24 changes: 0 additions & 24 deletions api/avro4k-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ public final class com/github/avrokotlin/avro4k/AvroKt {
public static final fun schema (Lcom/github/avrokotlin/avro4k/Avro;Lkotlinx/serialization/KSerializer;)Lorg/apache/avro/Schema;
}

public synthetic class com/github/avrokotlin/avro4k/AvroLogicalType$Impl : com/github/avrokotlin/avro4k/AvroLogicalType {
public fun <init> (Lkotlin/reflect/KClass;)V
public final synthetic fun value ()Ljava/lang/Class;
}

public abstract interface annotation class com/github/avrokotlin/avro4k/AvroNamespaceOverride : java/lang/annotation/Annotation {
public abstract fun value ()Ljava/lang/String;
}
Expand Down Expand Up @@ -150,18 +145,12 @@ public synthetic class com/github/avrokotlin/avro4k/AvroProp$Impl : com/github/a
public final synthetic fun value ()Ljava/lang/String;
}

public synthetic class com/github/avrokotlin/avro4k/AvroSchema$Impl : com/github/avrokotlin/avro4k/AvroSchema {
public fun <init> (Lkotlin/reflect/KClass;)V
public final synthetic fun value ()Ljava/lang/Class;
}

public final class com/github/avrokotlin/avro4k/AvroSingleObjectKt {
public static final fun decodeFromByteArray (Lcom/github/avrokotlin/avro4k/AvroSingleObject;Lkotlinx/serialization/DeserializationStrategy;[B)Ljava/lang/Object;
public static final fun encodeToByteArray (Lcom/github/avrokotlin/avro4k/AvroSingleObject;Lorg/apache/avro/Schema;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)[B
}

public abstract interface class com/github/avrokotlin/avro4k/decoder/AvroDecoder : kotlinx/serialization/encoding/Decoder {
public abstract fun decodeValue ()Ljava/lang/Object;
public abstract fun getCurrentWriterSchema ()Lorg/apache/avro/Schema;
}

Expand Down Expand Up @@ -311,19 +300,6 @@ public final class com/github/avrokotlin/avro4k/serializer/LocalTimeSerializer :
public fun serializeGeneric (Lkotlinx/serialization/encoding/Encoder;Ljava/time/LocalTime;)V
}

public final class com/github/avrokotlin/avro4k/serializer/TimestampSerializer : com/github/avrokotlin/avro4k/serializer/AvroTimeSerializer {
public static final field INSTANCE Lcom/github/avrokotlin/avro4k/serializer/TimestampSerializer;
public synthetic fun deserializeAvro (Lcom/github/avrokotlin/avro4k/decoder/AvroDecoder;)Ljava/lang/Object;
public fun deserializeAvro (Lcom/github/avrokotlin/avro4k/decoder/AvroDecoder;)Ljava/sql/Timestamp;
public synthetic fun deserializeGeneric (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun deserializeGeneric (Lkotlinx/serialization/encoding/Decoder;)Ljava/sql/Timestamp;
public fun getLogicalType (Ljava/util/List;)Lorg/apache/avro/LogicalType;
public synthetic fun serializeAvro (Lcom/github/avrokotlin/avro4k/encoder/AvroEncoder;Ljava/lang/Object;)V
public fun serializeAvro (Lcom/github/avrokotlin/avro4k/encoder/AvroEncoder;Ljava/sql/Timestamp;)V
public synthetic fun serializeGeneric (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public fun serializeGeneric (Lkotlinx/serialization/encoding/Encoder;Ljava/sql/Timestamp;)V
}

public final class com/github/avrokotlin/avro4k/serializer/URLSerializer : kotlinx/serialization/KSerializer {
public static final field INSTANCE Lcom/github/avrokotlin/avro4k/serializer/URLSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
Expand Down
2 changes: 0 additions & 2 deletions src/main/kotlin/com/github/avrokotlin/avro4k/Avro.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import com.github.avrokotlin.avro4k.serializer.InstantSerializer
import com.github.avrokotlin.avro4k.serializer.LocalDateSerializer
import com.github.avrokotlin.avro4k.serializer.LocalDateTimeSerializer
import com.github.avrokotlin.avro4k.serializer.LocalTimeSerializer
import com.github.avrokotlin.avro4k.serializer.TimestampSerializer
import com.github.avrokotlin.avro4k.serializer.URLSerializer
import com.github.avrokotlin.avro4k.serializer.UUIDSerializer
import kotlinx.serialization.DeserializationStrategy
Expand Down Expand Up @@ -64,7 +63,6 @@ public sealed class Avro(
contextual(LocalDateSerializer)
contextual(LocalTimeSerializer)
contextual(LocalDateTimeSerializer)
contextual(TimestampSerializer)
}
)

Expand Down
19 changes: 2 additions & 17 deletions src/main/kotlin/com/github/avrokotlin/avro4k/annotations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialInfo
import kotlinx.serialization.descriptors.SerialDescriptor
import org.apache.avro.LogicalType
import org.apache.avro.Schema
import org.intellij.lang.annotations.Language
import kotlin.reflect.KClass

Expand Down Expand Up @@ -99,25 +98,11 @@ public annotation class AvroDefault(
public annotation class AvroEnumDefault

/**
* Allows to specify the schema of a property.
* Will be removed when we will be able to unwrap a nullable descriptor.
*/
@SerialInfo
@ExperimentalSerializationApi
@Target(AnnotationTarget.PROPERTY)
public annotation class AvroSchema(val value: KClass<out AvroSchemaSupplier>)

@ExperimentalSerializationApi
public interface AvroSchemaSupplier {
public fun getSchema(stack: List<AnnotatedLocation>): Schema
}

/**
* Allows to specify the logical type applied on the generated schema of a property.
*/
@SerialInfo
@ExperimentalSerializationApi
@Target(AnnotationTarget.PROPERTY)
public annotation class AvroLogicalType(val value: KClass<out AvroLogicalTypeSupplier>)
internal annotation class AvroLogicalType(val value: KClass<out AvroLogicalTypeSupplier>)

@ExperimentalSerializationApi
public interface AvroLogicalTypeSupplier {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import org.apache.avro.Schema
import org.apache.avro.generic.GenericFixed

public interface AvroDecoder : Decoder {
/**
* Provides the schema used to encode the current value.
* It won't return a union as the schema correspond to the actual value.
*/
@ExperimentalSerializationApi
public val currentWriterSchema: Schema

Expand All @@ -15,5 +19,11 @@ public interface AvroDecoder : Decoder {
@ExperimentalSerializationApi
public fun decodeFixed(): GenericFixed

/**
* Decode a value that corresponds to the [currentWriterSchema].
*
* You should prefer using directly [currentWriterSchema] to get the schema and then decode the value using the appropriate **decode*** method.
*/
@ExperimentalSerializationApi
public fun decodeValue(): Any
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.github.avrokotlin.avro4k.schema
import com.github.avrokotlin.avro4k.Avro
import com.github.avrokotlin.avro4k.AvroFixed
import com.github.avrokotlin.avro4k.AvroLogicalType
import com.github.avrokotlin.avro4k.AvroSchema
import com.github.avrokotlin.avro4k.internal.AvroSchemaGenerationException
import com.github.avrokotlin.avro4k.internal.jsonNode
import com.github.avrokotlin.avro4k.internal.nonNullSerialName
Expand Down Expand Up @@ -117,7 +116,6 @@ internal class ValueVisitor internal constructor(
logicalType = annotations.logicalType.getLogicalType(annotations)
}
when {
annotations.customSchema != null -> setSchema(annotations.customSchema.getSchema(annotations))
annotations.fixed != null -> visitFixed(annotations.fixed)
descriptor.isByteArray() -> visitByteArray()
else -> super.visitValue(descriptor)
Expand All @@ -127,10 +125,6 @@ internal class ValueVisitor internal constructor(
private fun AnnotatedElementOrType<AvroLogicalType>.getLogicalType(valueAnnotations: ValueAnnotations): LogicalType {
return this.annotation.value.newObjectInstance().getLogicalType(valueAnnotations.stack)
}

private fun AnnotatedElementOrType<AvroSchema>.getSchema(valueAnnotations: ValueAnnotations): Schema {
return this.annotation.value.newObjectInstance().getSchema(valueAnnotations.stack)
}
}

private fun <T : Any> KClass<T>.newObjectInstance(): T {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import com.github.avrokotlin.avro4k.AvroFixed
import com.github.avrokotlin.avro4k.AvroLogicalType
import com.github.avrokotlin.avro4k.AvroNamespaceOverride
import com.github.avrokotlin.avro4k.AvroProp
import com.github.avrokotlin.avro4k.AvroSchema
import com.github.avrokotlin.avro4k.internal.findAnnotation
import com.github.avrokotlin.avro4k.internal.findAnnotations
import com.github.avrokotlin.avro4k.internal.findElementAnnotation
Expand Down Expand Up @@ -72,20 +71,17 @@ internal data class FieldAnnotations(
internal data class ValueAnnotations(
val stack: List<AnnotatedLocation>,
val fixed: AnnotatedElementOrType<AvroFixed>?,
val customSchema: AnnotatedElementOrType<AvroSchema>?,
val logicalType: AnnotatedElementOrType<AvroLogicalType>?,
) {
constructor(descriptor: SerialDescriptor, elementIndex: Int) : this(
listOf(SimpleAnnotatedLocation(descriptor, elementIndex)),
AnnotatedElementOrType<AvroFixed>(descriptor, elementIndex),
AnnotatedElementOrType<AvroSchema>(descriptor, elementIndex),
AnnotatedElementOrType<AvroLogicalType>(descriptor, elementIndex)
)

constructor(descriptor: SerialDescriptor) : this(
listOf(SimpleAnnotatedLocation(descriptor)),
AnnotatedElementOrType<AvroFixed>(descriptor),
AnnotatedElementOrType<AvroSchema>(descriptor),
AnnotatedElementOrType<AvroLogicalType>(descriptor)
)
}
Expand Down Expand Up @@ -137,6 +133,5 @@ internal fun ValueAnnotations?.appendAnnotations(other: ValueAnnotations) =
ValueAnnotations(
fixed = this?.fixed ?: other.fixed,
logicalType = this?.logicalType ?: other.logicalType,
customSchema = this?.customSchema ?: other.customSchema,
stack = (this?.stack ?: emptyList()) + other.stack
)
43 changes: 0 additions & 43 deletions src/main/kotlin/com/github/avrokotlin/avro4k/serializer/date.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import kotlinx.serialization.encoding.Encoder
import org.apache.avro.LogicalType
import org.apache.avro.LogicalTypes
import org.apache.avro.Schema
import java.sql.Timestamp
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
Expand Down Expand Up @@ -179,48 +178,6 @@ public object LocalDateTimeSerializer : AvroTimeSerializer<LocalDateTime>(LocalD
}
}

public object TimestampSerializer : AvroTimeSerializer<Timestamp>(Timestamp::class, PrimitiveKind.LONG) {
override fun getLogicalType(inlinedStack: List<AnnotatedLocation>): LogicalType {
return LogicalTypes.timestampMillis()
}

override fun serializeAvro(
encoder: AvroEncoder,
value: Timestamp,
) {
encoder.encodeResolvingUnion({
with(encoder) {
BadEncodedValueError(value, encoder.currentWriterSchema, Schema.Type.STRING, Schema.Type.LONG)
}
}) { schema ->
when (schema.type) {
Schema.Type.LONG ->
when (schema.logicalType) {
is LogicalTypes.TimestampMillis, null -> encoder.encodeLong(value.toInstant().toEpochMilli())
is LogicalTypes.TimestampMicros -> encoder.encodeLong(value.toInstant().toEpochMicros())
else -> null
}

Schema.Type.STRING -> encoder.encodeString(value.toInstant().toString())
else -> null
}
}
}

override fun serializeGeneric(
encoder: Encoder,
value: Timestamp,
) {
encoder.encodeLong(value.toInstant().toEpochMilli())
}

override fun deserializeAvro(decoder: AvroDecoder): Timestamp = deserializeGeneric(decoder)

override fun deserializeGeneric(decoder: Decoder): Timestamp {
return Timestamp(decoder.decodeLong())
}
}

public object InstantSerializer : AvroTimeSerializer<Instant>(Instant::class, PrimitiveKind.LONG) {
override fun getLogicalType(inlinedStack: List<AnnotatedLocation>): LogicalType {
return LogicalTypes.timestampMillis()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import org.apache.avro.SchemaBuilder
import java.math.BigDecimal
import java.math.BigInteger
import java.net.URL
import java.sql.Timestamp
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
Expand Down Expand Up @@ -44,7 +43,6 @@ internal class LogicalTypesEncodingTest : StringSpec({
BigDecimal("123.45"),
LocalDate.ofEpochDay(18262),
LocalTime.ofSecondOfDay(45296),
Timestamp(1577889296000),
Instant.ofEpochSecond(1577889296),
Instant.ofEpochSecond(1577889296, 424000),
UUID.fromString("123e4567-e89b-12d3-a456-426614174000"),
Expand All @@ -61,7 +59,6 @@ internal class LogicalTypesEncodingTest : StringSpec({
null,
null,
null,
null,
null
)

Expand All @@ -82,7 +79,6 @@ internal class LogicalTypesEncodingTest : StringSpec({
18262,
45296000,
1577889296000,
1577889296000,
1577889296000424,
"123e4567-e89b-12d3-a456-426614174000",
"http://example.com",
Expand All @@ -98,7 +94,6 @@ internal class LogicalTypesEncodingTest : StringSpec({
null,
null,
null,
null,
null
)
)
Expand All @@ -111,7 +106,6 @@ internal class LogicalTypesEncodingTest : StringSpec({
@Serializable(BigDecimalAsStringSerializer::class) val decimalString: BigDecimal,
@Contextual val date: LocalDate,
@Contextual val time: LocalTime,
@Contextual val timestamp: Timestamp,
@Contextual val instant: Instant,
@Serializable(InstantToMicroSerializer::class) val instantMicros: Instant,
@Contextual val uuid: UUID,
Expand All @@ -123,7 +117,6 @@ internal class LogicalTypesEncodingTest : StringSpec({
@Serializable(BigDecimalAsStringSerializer::class) val decimalStringNullable: BigDecimal?,
@Contextual val dateNullable: LocalDate?,
@Contextual val timeNullable: LocalTime?,
@Contextual val timestampNullable: Timestamp?,
@Contextual val instantNullable: Instant?,
@Serializable(InstantToMicroSerializer::class) val instantMicrosNullable: Instant?,
@Contextual val uuidNullable: UUID?,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import com.github.avrokotlin.avro4k.serializer.InstantToMicroSerializer
import com.github.avrokotlin.avro4k.serializer.LocalDateSerializer
import com.github.avrokotlin.avro4k.serializer.LocalDateTimeSerializer
import com.github.avrokotlin.avro4k.serializer.LocalTimeSerializer
import com.github.avrokotlin.avro4k.serializer.TimestampSerializer
import io.kotest.core.spec.style.FunSpec
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.nullable
Expand All @@ -20,7 +19,6 @@ internal class DateSchemaTest : FunSpec({
LocalTimeSerializer to LogicalTypes.timeMillis().addToSchema(Schema.create(Schema.Type.INT)),
LocalDateTimeSerializer to LogicalTypes.timestampMillis().addToSchema(Schema.create(Schema.Type.LONG)),
InstantSerializer to LogicalTypes.timestampMillis().addToSchema(Schema.create(Schema.Type.LONG)),
TimestampSerializer to LogicalTypes.timestampMillis().addToSchema(Schema.create(Schema.Type.LONG)),
InstantToMicroSerializer to LogicalTypes.timestampMicros().addToSchema(Schema.create(Schema.Type.LONG))
).forEach { (serializer: KSerializer<*>, expected) ->
test("generate date logical type for $serializer") {
Expand Down