Skip to content

Commit

Permalink
Added map and array types to avro type hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
sksamuel committed Apr 15, 2024
1 parent 018076d commit b4a5fed
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ fun interface Encoder<T> {
Int::class -> IntEncoder
Long::class -> LongEncoder
BigDecimal::class -> BigDecimalStringEncoder
Set::class -> GenericArraySetEncoder(encoderFor(type.arguments.first().type!!))
List::class -> GenericArrayListEncoder(encoderFor(type.arguments.first().type!!))
Set::class -> SetEncoder(encoderFor(type.arguments.first().type!!))
List::class -> ListEncoder(encoderFor(type.arguments.first().type!!))
Map::class -> MapEncoder(encoderFor(type.arguments[1].type!!))
is KClass<*> -> if (classifier.java.isEnum) EnumEncoder<Enum<*>>() else error("Unsupported type $type")
else -> error("Unsupported type $type")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import org.apache.avro.generic.GenericData
/**
* An [Encoder] for Arrays of [T] that encodes into an Avro [GenericArray].
*/
class GenericArrayArrayEncoder<T>(private val encoder: Encoder<T>) : Encoder<Array<T>> {
class ArrayEncoder<T>(private val encoder: Encoder<T>) : Encoder<Array<T>> {
override fun encode(schema: Schema, value: Array<T>): Any {
require(schema.type == Schema.Type.ARRAY)
val elements = value.map { encoder.encode(schema.elementType, it) }
Expand All @@ -18,7 +18,7 @@ class GenericArrayArrayEncoder<T>(private val encoder: Encoder<T>) : Encoder<Arr
/**
* An [Encoder] for Lists of [T] that encodes into an Avro [GenericArray].
*/
class GenericArrayListEncoder<T>(private val encoder: Encoder<T>) : Encoder<List<T>> {
class ListEncoder<T>(private val encoder: Encoder<T>) : Encoder<List<T>> {
override fun encode(schema: Schema, value: List<T>): Any {
require(schema.type == Schema.Type.ARRAY)
val elements = value.map { encoder.encode(schema.elementType, it) }
Expand All @@ -29,7 +29,7 @@ class GenericArrayListEncoder<T>(private val encoder: Encoder<T>) : Encoder<List
/**
* An [Encoder] for Sets of [T] that encodes into an Avro [GenericArray].
*/
class GenericArraySetEncoder<T>(private val encoder: Encoder<T>) : Encoder<Set<T>> {
class SetEncoder<T>(private val encoder: Encoder<T>) : Encoder<Set<T>> {
override fun encode(schema: Schema, value: Set<T>): GenericArray<Any> {
require(schema.type == Schema.Type.ARRAY)
val elements = value.map { encoder.encode(schema.elementType, it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,22 @@ class DataClassGenerator {
}

private fun member(field: Schema.Field): Member {
val type = when (field.schema().type) {
Schema.Type.RECORD -> Type.RecordType(field.schema().namespace, field.schema().name)
return Member(field.name(), schema(field.schema()))
}

private fun schema(schema: Schema): Type {
return when (val type = schema.type) {
Schema.Type.RECORD -> Type.RecordType(schema.namespace, schema.name)
Schema.Type.STRING -> Type.StringType
Schema.Type.INT -> Type.IntType
Schema.Type.LONG -> Type.LongType
Schema.Type.FLOAT -> Type.FloatType
Schema.Type.DOUBLE -> Type.DoubleType
Schema.Type.BOOLEAN -> Type.BooleanType
Schema.Type.ARRAY -> Type.ArrayType(schema(schema.elementType))
Schema.Type.MAP -> Type.ArrayType(schema(schema.valueType))
else -> error("Invalid code path")
}
return Member(field.name(), type)
}
}

Expand All @@ -42,6 +47,9 @@ sealed interface Type {
object FloatType : Type
object DoubleType : Type

data class ArrayType(val elementType: Type) : Type
data class MapType(val valueType: Type) : Type

// a nullable type wraps any other type, denoting that it is permitted to be null
// this is analogous to Avro's union type, with two elements - null and another
data class Nullable(val element: Type) : Type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ object DataClassWriter {
is Type.RecordType -> type.packageName + "." + type.className
Type.StringType -> "String"
is Type.Nullable -> typeToString(type.element) + "?"
is Type.ArrayType -> "List<${typeToString(type.elementType)}>"
is Type.MapType -> "Map<String, ${typeToString(type.valueType)}>"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class RecordDecoderGenerator {
is Type.Nullable -> TODO()
is Type.RecordType -> TODO()
Type.StringType -> "StringDecoder.decode($getSchema, $getValue)"
is Type.ArrayType -> "ListDecoder.decode($getSchema, $getValue)"
is Type.MapType -> "MapDecoder.decode($getSchema, $getValue)"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class RecordEncoderGenerator {
is Type.Nullable -> TODO()
is Type.RecordType -> TODO()
Type.StringType -> "StringEncoder.encode($getSchema, value.${member.name})"
is Type.ArrayType -> "ListEncoder.encode($getSchema, value.${member.name})"
is Type.MapType -> "MapEncoder.encode($getSchema, value.${member.name})"
}
}
}

0 comments on commit b4a5fed

Please sign in to comment.