Last active
February 26, 2016 05:21
-
-
Save echojc/ab4c7d2d758ab0f78442 to your computer and use it in GitHub Desktop.
In response to a comment on http://blog.echo.sh/2013/11/04/exploring-scala-macros-map-to-case-class-conversion.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait MapReader[T] { | |
// should really return Option[T], but let's keep it simple in this example | |
def read(map: Map[String, Any], key: String): T | |
} | |
object MapReader extends MapReaderLowPriorityImplicits { | |
// convenience method to retrieve implicit instance explicitly | |
def apply[T: MapReader]: MapReader[T] = implicitly[MapReader[T]] | |
// these implicits are always implicitly available as long as `MapReader` is in scope | |
implicit object IntMapReader extends MapReader[Int] { | |
def read(map: Map[String, Any], key: String): Int = | |
map(key).asInstanceOf[Int] | |
} | |
implicit object StringMapReader extends MapReader[String] { | |
def read(map: Map[String, Any], key: String): String = | |
map(key).toString | |
} | |
// etc. for all the basic types | |
} | |
// these are only attempted if none of the implicits in the companion object work | |
trait MapReaderLowPriorityImplicits { | |
implicit def caseClassMapReader[T]: MapReader[T] = macro caseClassMapReaderImpl | |
def caseClassMapReaderImpl[T: c.WeakTypeTag](c: Context): c.Expr[MapReader[T]] = { | |
// ... | |
// rest of the code from http://blog.echo.sh/2013/11/04/exploring-scala-macros-map-to-case-class-conversion.html | |
// ... | |
val fromMapParams = fields.map { field ⇒ | |
val name = field.name | |
val decoded = name.decoded | |
val returnType = tpe.declaration(name).typeSignature | |
q"MapReader[$returnType].read(map, $decoded)" | |
} | |
c.Expr[MapReader[T]] { q""" | |
new MapReader[$tpe] { | |
def read(map: Map[String, Any], key: String): $tpe = | |
$companion(..$fromMapParams) | |
} | |
""" } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment