Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
s/flattened/flatten/g
  • Loading branch information
gaborbarna committed Feb 3, 2018
commit ec68115a1851e2eebc342a190a9dfb80c7c0b61c
28 changes: 14 additions & 14 deletions core/src/main/scala/ste/encoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import scala.annotation.StaticAnnotation
import scala.collection.generic.IsTraversableOnce

final class Meta(val metadata: Metadata) extends StaticAnnotation
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have made this a case class?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think we should do that, and remove the val keyword.

final case class Flattened(times: Int = 1, keys: Seq[String] = Seq()) extends StaticAnnotation
final case class Flatten(times: Int = 1, keys: Seq[String] = Seq()) extends StaticAnnotation

@annotation.implicitNotFound("""
Type ${A} does not have a DataTypeEncoder defined in the library.
Expand Down Expand Up @@ -85,7 +85,7 @@ sealed trait AnnotatedStructTypeEncoder[A] {
}

object AnnotatedStructTypeEncoder extends MediumPriorityImplicits {
type Encode = (Seq[Metadata], Seq[Option[Flattened]]) => StructType
type Encode = (Seq[Metadata], Seq[Option[Flatten]]) => StructType

def pure[A](enc: Encode): AnnotatedStructTypeEncoder[A] =
new AnnotatedStructTypeEncoder[A] {
Expand All @@ -101,22 +101,22 @@ trait LowPriorityImplicits {
witness: Witness.Aux[K],
hEncoder: Lazy[DataTypeEncoder[H]],
tEncoder: AnnotatedStructTypeEncoder[T]
): AnnotatedStructTypeEncoder[FieldType[K, H] :: T] = AnnotatedStructTypeEncoder.pure { (metadata, flattened) =>
): AnnotatedStructTypeEncoder[FieldType[K, H] :: T] = AnnotatedStructTypeEncoder.pure { (metadata, flatten) =>
val fieldName = witness.value.name
val dt = hEncoder.value.encode
val fields = flattened.head.flatMap(f => hEncoder.value.fields.map(flattenFields(_, dt, fieldName, f))).getOrElse(
val fields = flatten.head.flatMap(f => hEncoder.value.fields.map(flattenFields(_, dt, fieldName, f))).getOrElse(
Seq(StructField(fieldName, dt, hEncoder.value.nullable, metadata.head)))
val tail = tEncoder.encode(metadata.tail, flattened.tail)
val tail = tEncoder.encode(metadata.tail, flatten.tail)
StructType(fields ++ tail.fields)
}

private def flattenFields(fields: Seq[StructField], dt: DataType, prefix: String, flattened: Flattened) =
(dt, flattened) match {
case (_: ArrayType, Flattened(times, _)) if times > 1 =>
private def flattenFields(fields: Seq[StructField], dt: DataType, prefix: String, flatten: Flatten) =
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we specify the return type?

(dt, flatten) match {
case (_: ArrayType, Flatten(times, _)) if times > 1 =>
(0 until times).flatMap(i => fields.map(prefixStructField(_, s"$prefix.$i")))
case (_: MapType, Flattened(_, keys)) if keys.nonEmpty =>
case (_: MapType, Flatten(_, keys)) if keys.nonEmpty =>
keys.flatMap(k => fields.map(prefixStructField(_, s"$prefix.$k")))
case (_, Flattened(_, _)) => fields.map(prefixStructField(_, prefix))
case (_, Flatten(_, _)) => fields.map(prefixStructField(_, prefix))
}

private def prefixStructField(f: StructField, prefix: String) =
Expand All @@ -126,14 +126,14 @@ trait LowPriorityImplicits {
implicit
generic: LabelledGeneric.Aux[A, H],
metaAnnotations: Annotations.Aux[Meta, A, HA],
flattenedAnnotations: Annotations.Aux[Flattened, A, HF],
flattenAnnotations: Annotations.Aux[Flatten, A, HF],
hEncoder: Lazy[AnnotatedStructTypeEncoder[H]],
metaToList: ToList[HA, Option[Meta]],
flattenedToList: ToList[HF, Option[Flattened]]
flattenToList: ToList[HF, Option[Flatten]]
): StructTypeEncoder[A] = {
val metadata = metaAnnotations().toList[Option[Meta]].map(extractMetadata)
val flattened = flattenedAnnotations().toList[Option[Flattened]]
StructTypeEncoder.pure(hEncoder.value.encode(metadata, flattened))
val flatten = flattenAnnotations().toList[Option[Flatten]]
StructTypeEncoder.pure(hEncoder.value.encode(metadata, flatten))
}

private val extractMetadata: Option[Meta] => Metadata =
Expand Down
2 changes: 1 addition & 1 deletion core/src/test/scala/ste/StructTypeEncoderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class StructTypeEncoderSpec extends FlatSpec with Matchers {
.build

case class Foo(a: String, @Meta(metadata) b: Int)
case class Bar(@Flattened(2) a: Seq[Foo], @Flattened(1, Seq("x", "y")) b: Map[Symbol, Foo], @Flattened c: Foo)
case class Bar(@Flatten(2) a: Seq[Foo], @Flatten(1, Seq("x", "y")) b: Map[Symbol, Foo], @Flatten c: Foo)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use Map[String, Foo] here as the keys in flatten are Strings anyway.

StructTypeEncoder[Bar].encode shouldBe StructType(
StructField("a.0.a", StringType, false) ::
StructField("a.0.b", IntegerType, false, metadata) ::
Expand Down