Skip to content

Commit

Permalink
Merge pull request #205 from Chuckame/explicit-api-mode
Browse files Browse the repository at this point in the history
build: Explicit API mode to prevent exposing internal stuff
  • Loading branch information
Chuckame authored May 3, 2024
2 parents 325bd3f + a6df754 commit e66ed3e
Show file tree
Hide file tree
Showing 73 changed files with 911 additions and 369 deletions.
444 changes: 444 additions & 0 deletions api/avro4k-core.api

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

buildscript {
Expand All @@ -22,6 +23,7 @@ plugins {
alias(libs.plugins.github.versions)
alias(libs.plugins.nexus.publish)
alias(libs.plugins.spotless)
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.14.0"
}

tasks {
Expand All @@ -42,11 +44,25 @@ dependencies {
testImplementation(libs.kotest.property)
}

kotlin {
explicitApi = ExplicitApiMode.Strict
}

apiValidation {
nonPublicMarkers.add("kotlinx.serialization.ExperimentalSerializationApi")
}

tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.apiVersion = "1.6"
kotlinOptions.languageVersion = "1.6"
kotlinOptions.freeCompilerArgs += listOf("-opt-in=kotlinx.serialization.ExperimentalSerializationApi", "-opt-in=kotlin.RequiresOptIn", "-Xcontext-receivers")
kotlinOptions.freeCompilerArgs +=
listOf(
"-Xexplicit-api=strict",
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
"-opt-in=kotlin.RequiresOptIn",
"-Xcontext-receivers"
)
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
64 changes: 32 additions & 32 deletions src/main/kotlin/com/github/avrokotlin/avro4k/Avro.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ import java.util.concurrent.ConcurrentHashMap
/**
* The goal of this class is to serialize and deserialize in avro binary format, not in GenericRecords.
*/
sealed class Avro(
val configuration: AvroConfiguration,
val serializersModule: SerializersModule,
public sealed class Avro(
public val configuration: AvroConfiguration,
public val serializersModule: SerializersModule,
) {
private val schemaCache: MutableMap<SerialDescriptor, Schema> = ConcurrentHashMap()
internal val recordResolver = RecordResolver(this)
internal val unionResolver = UnionResolver()
internal val enumResolver = EnumResolver()

companion object Default : Avro(
public companion object Default : Avro(
AvroConfiguration(),
SerializersModule {
contextual(UUIDSerializer)
Expand All @@ -64,15 +64,15 @@ sealed class Avro(
}
)

fun schema(descriptor: SerialDescriptor): Schema {
public fun schema(descriptor: SerialDescriptor): Schema {
return schemaCache.getOrPut(descriptor) {
lateinit var output: Schema
ValueVisitor(this) { output = it }.visitValue(descriptor)
return output
}
}

fun <T> encodeToStream(
public fun <T> encodeToStream(
writerSchema: Schema,
serializer: SerializationStrategy<T>,
value: T,
Expand All @@ -89,7 +89,7 @@ sealed class Avro(
avroEncoder.flush()
}

fun <T> encodeToByteArray(
public fun <T> encodeToByteArray(
writerSchema: Schema,
serializer: SerializationStrategy<T>,
value: T,
Expand All @@ -99,7 +99,7 @@ sealed class Avro(
return outputStream.toByteArray()
}

fun <T> encodeToGenericData(
public fun <T> encodeToGenericData(
writerSchema: Schema,
serializer: SerializationStrategy<T>,
value: T,
Expand All @@ -111,7 +111,7 @@ sealed class Avro(
return result
}

fun <T> decodeFromStream(
public fun <T> decodeFromStream(
writerSchema: Schema,
deserializer: DeserializationStrategy<T>,
inputStream: InputStream,
Expand All @@ -125,15 +125,15 @@ sealed class Avro(
return decodeFromGenericData(writerSchema, deserializer, genericData)
}

fun <T> decodeFromByteArray(
public fun <T> decodeFromByteArray(
writerSchema: Schema,
deserializer: DeserializationStrategy<T>,
bytes: ByteArray,
): T {
return decodeFromStream(writerSchema, deserializer, ByteArrayInputStream(bytes))
}

fun <T> decodeFromGenericData(
public fun <T> decodeFromGenericData(
writerSchema: Schema,
deserializer: DeserializationStrategy<T>,
value: Any?,
Expand All @@ -143,7 +143,7 @@ sealed class Avro(
}
}

fun Avro(
public fun Avro(
from: Avro = Avro,
builderAction: AvroBuilder.() -> Unit,
): Avro {
Expand All @@ -152,13 +152,13 @@ fun Avro(
return AvroImpl(builder.build(), from.serializersModule.overwriteWith(builder.serializersModule))
}

class AvroBuilder internal constructor(avro: Avro) {
var fieldNamingStrategy: FieldNamingStrategy = avro.configuration.fieldNamingStrategy
var implicitNulls: Boolean = avro.configuration.implicitNulls
var encodedAs: EncodedAs = avro.configuration.encodedAs
var serializersModule: SerializersModule = EmptySerializersModule()
public class AvroBuilder internal constructor(avro: Avro) {
public var fieldNamingStrategy: FieldNamingStrategy = avro.configuration.fieldNamingStrategy
public var implicitNulls: Boolean = avro.configuration.implicitNulls
public var encodedAs: EncodedAs = avro.configuration.encodedAs
public var serializersModule: SerializersModule = EmptySerializersModule()

fun build() =
public fun build(): AvroConfiguration =
AvroConfiguration(
fieldNamingStrategy = fieldNamingStrategy,
implicitNulls = implicitNulls,
Expand All @@ -171,52 +171,52 @@ private class AvroImpl(configuration: AvroConfiguration, serializersModule: Seri

// schema gen extensions

inline fun <reified T> Avro.schema(): Schema {
public inline fun <reified T> Avro.schema(): Schema {
val serializer = serializersModule.serializer<T>()
return schema(serializer.descriptor)
}

fun <T> Avro.schema(serializer: KSerializer<T>): Schema {
public fun <T> Avro.schema(serializer: KSerializer<T>): Schema {
return schema(serializer.descriptor)
}

// encoding extensions

inline fun <reified T> Avro.encodeToByteArray(value: T): ByteArray {
public inline fun <reified T> Avro.encodeToByteArray(value: T): ByteArray {
val serializer = serializersModule.serializer<T>()
return encodeToByteArray(schema(serializer), serializer, value)
}

inline fun <reified T> Avro.encodeToByteArray(
public inline fun <reified T> Avro.encodeToByteArray(
writerSchema: Schema,
value: T,
): ByteArray {
val serializer = serializersModule.serializer<T>()
return encodeToByteArray(writerSchema, serializer, value)
}

inline fun <reified T> Avro.encodeToGenericData(value: T): Any? {
public inline fun <reified T> Avro.encodeToGenericData(value: T): Any? {
val serializer = serializersModule.serializer<T>()
return encodeToGenericData(schema(serializer), serializer, value)
}

inline fun <reified T> Avro.encodeToGenericData(
public inline fun <reified T> Avro.encodeToGenericData(
writerSchema: Schema,
value: T,
): Any? {
val serializer = serializersModule.serializer<T>()
return encodeToGenericData(writerSchema, serializer, value)
}

inline fun <reified T> Avro.encodeToStream(
public inline fun <reified T> Avro.encodeToStream(
value: T,
outputStream: OutputStream,
) {
val serializer = serializersModule.serializer<T>()
encodeToStream(schema(serializer), serializer, value, outputStream)
}

inline fun <reified T> Avro.encodeToStream(
public inline fun <reified T> Avro.encodeToStream(
writerSchema: Schema,
value: T,
outputStream: OutputStream,
Expand All @@ -227,41 +227,41 @@ inline fun <reified T> Avro.encodeToStream(

// decoding extensions

inline fun <reified T> Avro.decodeFromStream(inputStream: InputStream): T {
public inline fun <reified T> Avro.decodeFromStream(inputStream: InputStream): T {
val serializer = serializersModule.serializer<T>()
return decodeFromStream(schema(serializer.descriptor), serializer, inputStream)
}

inline fun <reified T> Avro.decodeFromStream(
public inline fun <reified T> Avro.decodeFromStream(
writerSchema: Schema,
inputStream: InputStream,
): T {
val serializer = serializersModule.serializer<T>()
return decodeFromStream(writerSchema, serializer, inputStream)
}

inline fun <reified T> Avro.decodeFromByteArray(bytes: ByteArray): T {
public inline fun <reified T> Avro.decodeFromByteArray(bytes: ByteArray): T {
val serializer = serializersModule.serializer<T>()
return decodeFromByteArray(schema(serializer.descriptor), serializer, bytes)
}

inline fun <reified T> Avro.decodeFromByteArray(
public inline fun <reified T> Avro.decodeFromByteArray(
writerSchema: Schema,
bytes: ByteArray,
): T {
val serializer = serializersModule.serializer<T>()
return decodeFromByteArray(writerSchema, serializer, bytes)
}

inline fun <reified T> Avro.decodeFromGenericData(
public inline fun <reified T> Avro.decodeFromGenericData(
writerSchema: Schema,
value: Any?,
): T {
val deserializer = serializersModule.serializer<T>()
return decodeFromGenericData(writerSchema, deserializer, value)
}

inline fun <reified T> Avro.decodeFromGenericData(value: GenericContainer?): T? {
public inline fun <reified T> Avro.decodeFromGenericData(value: GenericContainer?): T? {
if (value == null) return null
val deserializer = serializersModule.serializer<T>()
return decodeFromGenericData(value.schema, deserializer, value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.github.avrokotlin.avro4k
import com.github.avrokotlin.avro4k.schema.FieldNamingStrategy
import kotlinx.serialization.ExperimentalSerializationApi

data class AvroConfiguration(
public data class AvroConfiguration(
/**
* The naming strategy to use for records' fields name.
*
Expand All @@ -25,7 +25,7 @@ data class AvroConfiguration(
)

@ExperimentalSerializationApi
enum class EncodedAs {
public enum class EncodedAs {
BINARY,
JSON_COMPACT,
JSON_PRETTY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import java.io.OutputStream
* [spec](https://avro.apache.org/docs/1.11.1/specification/#object-container-files)
*/
@ExperimentalSerializationApi
class AvroObjectContainerFile(
val avro: Avro = Avro,
public class AvroObjectContainerFile(
@PublishedApi
internal val avro: Avro = Avro,
) {
fun <T> encodeToStream(
public fun <T> encodeToStream(
schema: Schema,
serializer: SerializationStrategy<T>,
values: Sequence<T>,
Expand All @@ -43,7 +44,7 @@ class AvroObjectContainerFile(
// don't close the stream, the caller should do it
}

fun <T> decodeFromStream(
public fun <T> decodeFromStream(
deserializer: DeserializationStrategy<T>,
inputStream: InputStream,
metadataDumper: AvroObjectContainerFileMetadataDumper.() -> Unit = {},
Expand All @@ -57,7 +58,7 @@ class AvroObjectContainerFile(
}.constrainOnce()
}

inline fun <reified T> AvroObjectContainerFile.encodeToStream(
public inline fun <reified T> AvroObjectContainerFile.encodeToStream(
values: Sequence<T>,
outputStream: OutputStream,
noinline builder: AvroObjectContainerFileBuilder.() -> Unit = {},
Expand All @@ -66,52 +67,52 @@ inline fun <reified T> AvroObjectContainerFile.encodeToStream(
encodeToStream(avro.schema(serializer), serializer, values, outputStream, builder)
}

inline fun <reified T> AvroObjectContainerFile.decodeFromStream(
public inline fun <reified T> AvroObjectContainerFile.decodeFromStream(
inputStream: InputStream,
noinline metadataDumper: AvroObjectContainerFileMetadataDumper.() -> Unit = {},
): Sequence<T> {
val serializer = avro.serializersModule.serializer<T>()
return decodeFromStream(serializer, inputStream, metadataDumper)
}

class AvroObjectContainerFileBuilder(private val fileWriter: DataFileWriter<*>) {
fun metadata(
public class AvroObjectContainerFileBuilder(private val fileWriter: DataFileWriter<*>) {
public fun metadata(
key: String,
value: ByteArray,
) {
fileWriter.setMeta(key, value)
}

fun metadata(
public fun metadata(
key: String,
value: String,
) {
fileWriter.setMeta(key, value)
}

fun metadata(
public fun metadata(
key: String,
value: Long,
) {
fileWriter.setMeta(key, value)
}

fun codec(codec: CodecFactory) {
public fun codec(codec: CodecFactory) {
fileWriter.setCodec(codec)
}
}

class AvroObjectContainerFileMetadataDumper(private val fileStream: DataFileStream<*>) {
fun metadata(key: String): MetadataAccessor? {
public class AvroObjectContainerFileMetadataDumper(private val fileStream: DataFileStream<*>) {
public fun metadata(key: String): MetadataAccessor? {
return fileStream.getMeta(key)?.let { MetadataAccessor(it) }
}

inner class MetadataAccessor(private val value: ByteArray) {
fun asBytes(): ByteArray = value
public inner class MetadataAccessor(private val value: ByteArray) {
public fun asBytes(): ByteArray = value

fun asString(): String = value.decodeToString()
public fun asString(): String = value.decodeToString()

fun asLong(): Long = asString().toLong()
public fun asLong(): Long = asString().toLong()
}
}

Expand Down
Loading

0 comments on commit e66ed3e

Please sign in to comment.