in parquet/src/main/scala/magnolify/parquet/ParquetField.scala [305:369]
implicit def ptIterable[T, C[T]](implicit
t: ParquetField[T],
ti: C[T] => Iterable[T],
fc: FactoryCompat[T, C[T]],
pa: ParquetArray
): ParquetField[C[T]] = {
new ParquetField[C[T]] {
override val hasAvroArray: Boolean = pa match {
case ParquetArray.default => false
case ParquetArray.AvroCompat.avroCompat => true
}
override def buildSchema(cm: CaseMapper): Type = {
val repeatedSchema = Schema.setRepetition(t.schema(cm), Repetition.REPEATED)
if (hasAvroArray) {
Types
.requiredGroup()
.addField(Schema.rename(repeatedSchema, AvroArrayField))
.as(LogicalTypeAnnotation.listType())
.named("iterable")
} else {
repeatedSchema
}
}
override protected val isGroup: Boolean = hasAvroArray
override protected def isEmpty(v: C[T]): Boolean = v.forall(t.isEmpty)
override def write(c: RecordConsumer, v: C[T])(cm: CaseMapper): Unit =
if (hasAvroArray) {
c.startField(AvroArrayField, 0)
v.foreach(t.writeGroup(c, _)(cm))
c.endField(AvroArrayField, 0)
} else {
v.foreach(t.writeGroup(c, _)(cm))
}
override def newConverter: TypeConverter[C[T]] = {
val buffered = t.newConverter
.asInstanceOf[TypeConverter.Buffered[T]]
.withRepetition(Repetition.REPEATED)
val arrayConverter = new TypeConverter.Delegate[T, C[T]](buffered) {
override def get: C[T] = inner.get(fc.fromSpecific)
}
if (hasAvroArray) {
new GroupConverter with TypeConverter.Buffered[C[T]] {
override def getConverter(fieldIndex: Int): Converter = {
require(fieldIndex == 0, "Avro array field index != 0")
arrayConverter
}
override def start(): Unit = ()
override def end(): Unit = addValue(arrayConverter.get)
override def get: C[T] = get(_.headOption.getOrElse(fc.newBuilder.result()))
}
} else {
arrayConverter
}
}
override def fieldDocs(cm: CaseMapper): Map[String, String] = t.fieldDocs(cm)
override val typeDoc: Option[String] = None
}
}