Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
31 changes: 25 additions & 6 deletions core/src/main/scala/Pickler.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package gkit

import scalaz._
import Leibniz.===
import Liskov.<~<
import scalaz.syntax.std.option._
import scalaz.syntax.either._

Expand All @@ -13,13 +15,30 @@ trait Pickler[A, B] {

def unpickle(b: B, path: List[String] = Nil): String \/ A

class Typecheck[A] {
def apply[B, C](b: B, path: List[String])(f: A => C)
(implicit tpble: Typeable[A], tm: Manifest[A]): String \/ C = {
def errMsg = s"""type mismatch at `${path.mkString(".")}': expected: ${tm.runtimeClass.getName}, found: ${b.toString}"""
b.cast[A].cata(f(_).right, errMsg.left)
}
}

object Pickler extends LowerPriorityPickler {
implicit def leibPickler[A, B](implicit f: A === B): Pickler[A, B] = new Pickler[A, B] {
def pickle(a: A): B = f(a)
def unpickle(b: B, path: List[String]): String \/ A = Leibniz.symm[Nothing, Any, A, B](f)(b).right
}

}

trait LowerPriorityPickler {
implicit def liskovPickler[A, B](implicit f: A <~< B, tpble: Typeable[A], tm: Manifest[A]): Pickler[A, B] = new Pickler[A, B] {
def pickle(a: A): B = f(a)
def unpickle(b: B, path: List[String]): String \/ A =
typecheck[A](b, path)(identity)
}

def typecheck[A]: Typecheck[A] = new Typecheck[A]
}

class Typecheck[A] {
def apply[B, C](b: B, path: List[String])(f: A => C)
(implicit tpble: Typeable[A], tm: Manifest[A]): String \/ C = {
def errMsg = s"""type mismatch at `${path.mkString(".")}': expected: ${tm.runtimeClass.getName}, found: ${b.toString}"""
b.cast[A].cata(f(_).right, errMsg.left)
}
}
15 changes: 1 addition & 14 deletions mongo/src/main/scala/BSONPickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ import scalaz.syntax.traverse._
import shapeless._
import shapeless.record._

trait BSONPickler[A] extends Pickler[A, BSONValue]

object BSONPickler {
import Pickler._

implicit def apply[A](implicit ev: LabelledTypeClass[BSONPickler]): BSONPickler[A] =
macro GenericMacros.deriveLabelledInstance[BSONPickler, A]
Expand Down Expand Up @@ -56,18 +55,6 @@ object BSONPickler {
typecheck[BSONDateTime](v, path)(dt => new DateTime(dt.value))
}

implicit def BSONObjectIDPickler: BSONPickler[BSONObjectID] = new BSONPickler[BSONObjectID] {
def pickle(boid: BSONObjectID): BSONValue = boid
def unpickle(v: BSONValue, path: List[String]): String \/ BSONObjectID =
typecheck[BSONObjectID](v, path)(identity)
}

implicit def BSONDocumentPickler: BSONPickler[BSONDocument] = new BSONPickler[BSONDocument] {
def pickle(doc: BSONDocument): BSONValue = doc
def unpickle(v: BSONValue, path: List[String]): String \/ BSONDocument =
typecheck[BSONDocument](v, path)(identity)
}

implicit def OptionBSONPickler[T](implicit bp: BSONPickler[T]): BSONPickler[Option[T]] = new BSONPickler[Option[T]] {
def pickle(t: Option[T]): BSONValue = t.map(bp.pickle).getOrElse(BSONUndefined)
def unpickle(v: BSONValue, path: List[String]): String \/ Option[T] =
Expand Down
6 changes: 5 additions & 1 deletion mongo/src/main/scala/package.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package gkit

package object mongo extends QueryPicklerInstances with GeneratorInstances
import reactivemongo.bson.BSONValue

package object mongo extends QueryPicklerInstances with GeneratorInstances {
type BSONPickler[A] = Pickler[A, BSONValue]
}
5 changes: 4 additions & 1 deletion play-gjson/src/main/scala/JSONPickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ import scalaz.syntax.traverse._
import shapeless._
import shapeless.record._

trait JSONPickler[A] extends Pickler[A, JsValue]
object `package` {
type JSONPickler[A] = Pickler[A, JsValue]
}

object JSONPickler {
import Pickler._

implicit def apply[A](implicit ev: LabelledTypeClass[JSONPickler]): JSONPickler[A] =
macro GenericMacros.deriveLabelledInstance[JSONPickler, A]
Expand Down
1 change: 1 addition & 0 deletions play-gresource-mongo/src/main/scala/PicklerInstances.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import scalaz.syntax.either._
import scalaz.syntax.std.option._

trait PicklerInstances {
import gkit.Pickler._

implicit def BSONObjectIDPickler: JSONPickler[BSONObjectID] =
new JSONPickler[BSONObjectID] {
Expand Down