Skip to content
This repository has been archived by the owner on Jul 25, 2023. It is now read-only.

Commit

Permalink
Restructure generic module to make tests compile (and pass)
Browse files Browse the repository at this point in the history
  • Loading branch information
rootmos committed May 19, 2018
1 parent 29c4171 commit 9dabacf
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 157 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package io.protoless.generic.decoding
package io.protoless.generic

import com.google.protobuf.CodedInputStream
import com.google.protobuf.{CodedInputStream, CodedOutputStream}
import shapeless.{Generic, HList, Nat}

import io.protoless.messages.Decoder.Result
import io.protoless.messages.decoders.{AutoDecoder, IncrementalDecoder}
import io.protoless.messages.encoders.{AutoEncoder, IncrementalEncoder}

trait AutoDecoderInstances extends IncrementalDecoderInstances {
trait AutoEncoderDecoderInstances extends IncrementalEncoderDecoderInstances {

implicit def decodeAuto[A, R <: HList](implicit
gen: Generic.Aux[A, R],
Expand All @@ -20,4 +21,14 @@ trait AutoDecoderInstances extends IncrementalDecoderInstances {
}
}

implicit def encodeAuto[A, R <: HList](implicit
gen: Generic.Aux[A, R],
encoder: IncrementalEncoder[R, Nat._1]
): AutoEncoder[A] = new AutoEncoder[A] {
override def encode(a: A, output: CodedOutputStream): Unit = {
encoder.encode(gen.to(a), output)
output.flush()
}
}

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package io.protoless.generic.decoding
package io.protoless.generic

import com.google.protobuf.CodedInputStream
import com.google.protobuf.{CodedInputStream, CodedOutputStream}

import shapeless.ops.nat.ToInt
import shapeless.{::, Generic, HList, HNil, Nat}
import shapeless.ops.nat.ToInt

import io.protoless.messages.decoders.CustomMappingDecoder
import io.protoless.fields.FieldDecoder
import io.protoless.messages.encoders.CustomMappingEncoder
import io.protoless.fields.{FieldEncoder, FieldDecoder}
import io.protoless.messages.Decoder.Result

trait CustomMappingDecoderInstances {
trait CustomMappingEncoderDecoderInstances extends IncrementalDecoderInstances {

implicit val decodeCustomMappingHNil: CustomMappingDecoder[HNil, HNil] = new CustomMappingDecoder[HNil, HNil] {
override def decode(input: CodedInputStream): Result[HNil] = Right(HNil)
Expand Down Expand Up @@ -54,4 +55,45 @@ trait CustomMappingDecoderInstances {
}
}
}

implicit val encodeCustomMappingHNil: CustomMappingEncoder[HNil, HNil] = new CustomMappingEncoder[HNil, HNil] {
override def encode(a: HNil, output: CodedOutputStream): Unit = {}
}

// Encode mapping specified with Nat (Nat._1 :: Nat._3 :: HNil)
implicit def encodeCustomMappingHList[H, T <: HList, L <: Nat, TN <: HList](implicit
hEncoder: FieldEncoder[H],
index: ToInt[L],
tEncoder: CustomMappingEncoder[T, TN]
): CustomMappingEncoder[H :: T, L :: TN] = new CustomMappingEncoder[H :: T, L :: TN] {
override def encode(a: H :: T, output: CodedOutputStream): Unit = {
val (h :: t) = a
hEncoder.write(index(), h, output)
tEncoder.encode(t, output)
}
}

// Encode mapping specified with Literal (1 :: 3 :: HNil)
implicit def encodeCustomMappingHListLiteral[H, T <: HList, L <: Int, TN <: HList](implicit
hEncoder: FieldEncoder[H],
index: ValueOf[L],
tEncoder: CustomMappingEncoder[T, TN]
): CustomMappingEncoder[H :: T, L :: TN] = new CustomMappingEncoder[H :: T, L :: TN] {
override def encode(a: H :: T, output: CodedOutputStream): Unit = {
val (h :: t) = a
hEncoder.write(valueOf[L], h, output)
tEncoder.encode(t, output)
}
}

implicit def encodeCustomMapping[A, L <: HList, R <: HList](implicit
gen: Generic.Aux[A, R],
encoder: CustomMappingEncoder[R, L]
): CustomMappingEncoder[A, L] = new CustomMappingEncoder[A, L] {
override def encode(a: A, output: CodedOutputStream): Unit = {
encoder.encode(gen.to(a), output)
output.flush()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.protoless.generic

trait IncrementalDecoderInstances {

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
package io.protoless.generic.decoding
package io.protoless.generic

import com.google.protobuf.CodedOutputStream
import com.google.protobuf.CodedInputStream
import shapeless.{::, Generic, HList, HNil, Nat, Succ}
import shapeless.ops.nat.ToInt

import io.protoless.messages.encoders.IncrementalEncoder
import io.protoless.fields.FieldEncoder
import io.protoless.messages.Decoder.Result
import io.protoless.messages.decoders.IncrementalDecoder
import io.protoless.fields.FieldDecoder

trait IncrementalDecoderInstances {
trait IncrementalEncoderDecoderInstances extends CustomMappingEncoderDecoderInstances {

implicit def encodeIncrementalHNil[N <: Nat]: IncrementalEncoder[HNil, N] = new IncrementalEncoder[HNil, N] {
override def encode(a: HNil, output: CodedOutputStream): Unit = {}
}

implicit def encodeIncrementalHList[H, T <: HList, N <: Nat](implicit
hEncoder: FieldEncoder[H],
index: ToInt[N],
tEncoder: IncrementalEncoder[T, Succ[N]]
): IncrementalEncoder[H :: T, N] = new IncrementalEncoder[H :: T, N] {
override def encode(a: H :: T, output: CodedOutputStream): Unit = {
val (h :: t) = a
hEncoder.write(index(), h, output)
tEncoder.encode(t, output)
}
}

implicit def encodeIncremental[A, N <: Nat, R <: HList](implicit
gen: Generic.Aux[A, R],
encoder: IncrementalEncoder[R, N]
): IncrementalEncoder[A, N] = new IncrementalEncoder[A, N] {
override def encode(a: A, output: CodedOutputStream): Unit = {
encoder.encode(gen.to(a), output)
output.flush()
}
}

implicit def decodeIncrementalHNil[N <: Nat]: IncrementalDecoder[HNil, N] = new IncrementalDecoder[HNil, N] {
override def decode(input: CodedInputStream): Result[HNil] = Right(HNil)
Expand Down Expand Up @@ -37,4 +67,5 @@ trait IncrementalDecoderInstances {
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
package io.protoless.generic.encoding.internal
package io.protoless.generic

import shapeless.Nat

import io.protoless.generic.encoding.IncrementalEncoderInstances
import io.protoless.messages.Encoder
import io.protoless.messages.{Encoder, Decoder}
import io.protoless.messages.encoders.IncrementalEncoder
import io.protoless.messages.decoders.IncrementalDecoder

/**
* Internal class allowing to restrict automatic derivation of type `A`.
*
* [[SemiAutoEncoder]] can only be retrieved with `io.protoless.generic.semiauto.deriveEncoder`.
*/
private[protoless] class SemiAutoEncoder[A](val underlying: Encoder[A])
private[protoless] class SemiAutoDecoder[A](val underlying: Decoder[A])

private[protoless] class SemiAutoEncoderInstances extends IncrementalEncoderInstances {
private[protoless] trait SemiAutoEncoderDecoderInstances extends IncrementalEncoderDecoderInstances {

implicit def encodeSemiAutoInstance[A](implicit encoder: IncrementalEncoder[A, Nat._1]): SemiAutoEncoder[A] = {
new SemiAutoEncoder[A](encoder)
}

implicit def decodeSemiAutoInstance[A](implicit decoder: IncrementalDecoder[A, Nat._1]): SemiAutoDecoder[A] = {
new SemiAutoDecoder[A](decoder)
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import shapeless.HList

import io.protoless.messages.decoders.CustomMappingDecoder
import io.protoless.messages.encoders.CustomMappingEncoder
import io.protoless.generic.decoding.{AutoDecoderInstances, CustomMappingDecoderInstances}
import io.protoless.generic.decoding.internal.{SemiAutoDecoder, SemiAutoDecoderInstances}
import io.protoless.generic.encoding.{AutoEncoderInstances, CustomMappingEncoderInstances}
import io.protoless.generic.encoding.internal.{SemiAutoEncoder, SemiAutoEncoderInstances}
import io.protoless.messages.{Decoder, Encoder}

package object generic {
Expand All @@ -20,13 +16,13 @@ package object generic {
* You can still derive [[messages.decoders.CustomMappingDecoder]] and [[messages.encoders.CustomMappingEncoder]]
* with `semiauto.deriveDecoder[A, L]` or by summoning a decoder with `CustomMappingDecoder[A, HList]` (idem for Encoders).
*/
object auto extends AutoDecoderInstances with CustomMappingDecoderInstances with AutoEncoderInstances with CustomMappingEncoderInstances
object auto extends AutoEncoderDecoderInstances

/**
* Allows to manually derive [[Decoder]] and [[Encoder]],
* either with `Automatic` strategy or `Custom Mapping` strategy.
*/
object semiauto extends SemiAutoEncoderInstances with SemiAutoDecoderInstances with CustomMappingDecoderInstances with CustomMappingEncoderInstances {
object semiauto extends SemiAutoEncoderDecoderInstances {

/**
* Derive an [[Decoder]] to decode a type `A` from a protobuf message, for which
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import io.protoless.tests.ProtolessSuite
import io.protoless.tests.instances.EqualityInstances
import io.protoless.tests.samples._
import io.protoless.tests.samples.TestCaseNestedCustomMapping.InnerNestedCustomMapping
import io.protoless.generic.SemiAutoEncoderDecoderInstances

class CustomMappingEncoderDecoderSuite extends ProtolessSuite with EqualityInstances with EncoderDecoderAssertions {
trait CustomMappingEncoderDecoderSuite extends ProtolessSuite with EqualityInstances with EncoderDecoderAssertions with SemiAutoEncoderDecoderInstances {

import io.protoless.generic.semiauto._
import io.protoless.generic.semiauto.{deriveEncoder, deriveDecoder}

// Fields number specified with Nat
type IndexSimple = Nat._2 :: Nat._5 :: Nat._13 :: Nat._16 :: HNil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import io.protoless.messages.{Decoder, Encoder}
import io.protoless.tests.ProtolessSuite
import io.protoless.tests.instances.EqualityInstances
import io.protoless.tests.samples._
import io.protoless.generic.SemiAutoEncoderDecoderInstances

class SemiAutoEncoderDecoderSuite extends ProtolessSuite with EqualityInstances with EncoderDecoderAssertions {
class SemiAutoEncoderDecoderSuite extends ProtolessSuite with EqualityInstances with EncoderDecoderAssertions with SemiAutoEncoderDecoderInstances {

import io.protoless.generic.semiauto._
import io.protoless.generic.semiauto.{deriveEncoder, deriveDecoder}

implicit val decoderTestCaseAllFields: Decoder[TestCaseAllFields] = deriveDecoder[TestCaseAllFields]
implicit val decoderTestCaseOptionalFields: Decoder[TestCaseOptionalFields] = deriveDecoder[TestCaseOptionalFields]
Expand Down

0 comments on commit 9dabacf

Please sign in to comment.