Skip to content

Commit

Permalink
Split ConfigConvert object into multiple traits (#171)
Browse files Browse the repository at this point in the history
* Split ConfigConvert object into multiple traits

* Split BasicConverters in simpler traits
  • Loading branch information
ruippeixotog authored and melrief committed Mar 21, 2017
1 parent c241057 commit 721603b
Show file tree
Hide file tree
Showing 5 changed files with 563 additions and 496 deletions.
130 changes: 130 additions & 0 deletions core/src/main/scala/pureconfig/BasicConverters.scala
@@ -0,0 +1,130 @@
package pureconfig

import java.net.{ URI, URL }
import java.nio.file.{ Path, Paths }
import java.time._
import java.util.UUID

import scala.concurrent.duration.{ Duration, FiniteDuration }

import com.typesafe.config._
import pureconfig.error._

/**
* Trait containing `ConfigConvert` instances for primitive types.
*/
trait PrimitiveConverters extends ConvertHelpers {

implicit val stringConfigConvert = fromStringReader[String](s => _ => Right(s))
implicit val booleanConfigConvert = fromNonEmptyStringReader[Boolean](catchReadError(_.toBoolean))
implicit val doubleConfigConvert = fromNonEmptyStringReader[Double](catchReadError({
case v if v.last == '%' => v.dropRight(1).toDouble / 100d
case v => v.toDouble
}))
implicit val floatConfigConvert = fromNonEmptyStringReader[Float](catchReadError({
case v if v.last == '%' => v.dropRight(1).toFloat / 100f
case v => v.toFloat
}))
implicit val intConfigConvert = fromNonEmptyStringReader[Int](catchReadError(_.toInt))
implicit val longConfigConvert = fromNonEmptyStringReader[Long](catchReadError(_.toLong))
implicit val shortConfigConvert = fromNonEmptyStringReader[Short](catchReadError(_.toShort))
}

/**
* Trait containing `ConfigConvert` instances for classes related to file system paths and URIs.
*/
trait UriAndPathConverters extends ConvertHelpers {

implicit val urlConfigConvert = fromNonEmptyStringConvert[URL](catchReadError(new URL(_)), _.toString)
implicit val uuidConfigConvert = fromNonEmptyStringConvert[UUID](catchReadError(UUID.fromString), _.toString)
implicit val pathConfigConvert = fromStringConvert[Path](catchReadError(Paths.get(_)), _.toString)
implicit val uriConfigConvert = fromStringConvert[URI](catchReadError(new URI(_)), _.toString)
}

/**
* Trait containing `ConfigConvert` instances for `java.time` classes.
*/
trait JavaTimeConverters extends ConvertHelpers {

implicit val instantConfigConvert: ConfigConvert[Instant] =
fromNonEmptyStringReader[Instant](catchReadError(Instant.parse))

implicit val zoneOffsetConfigConvert: ConfigConvert[ZoneOffset] =
fromNonEmptyStringReader[ZoneOffset](catchReadError(ZoneOffset.of))

implicit val zoneIdConfigConvert: ConfigConvert[ZoneId] =
fromNonEmptyStringReader[ZoneId](catchReadError(ZoneId.of))

implicit val periodConfigConvert: ConfigConvert[Period] =
fromNonEmptyStringReader[Period](catchReadError(Period.parse))

implicit val yearConfigConvert: ConfigConvert[Year] =
fromNonEmptyStringReader[Year](catchReadError(Year.parse))
}

/**
* Trait containing `ConfigConvert` instances for [[Duration]] and [[FiniteDuration]].
*/
trait DurationConverters extends ConvertHelpers {

implicit val durationConfigConvert: ConfigConvert[Duration] = {
fromNonEmptyStringConvert[Duration](DurationConvert.fromString, DurationConvert.fromDuration)
}

implicit val finiteDurationConfigConvert: ConfigConvert[FiniteDuration] = {
val fromString: String => Option[ConfigValueLocation] => Either[ConfigReaderFailure, FiniteDuration] = { string => location =>
DurationConvert.fromString(string)(location).right.flatMap {
case d: FiniteDuration => Right(d)
case _ => Left(CannotConvert(string, "FiniteDuration", s"Couldn't parse '$string' into a FiniteDuration because it's infinite.", location, None))
}
}
fromNonEmptyStringConvert[FiniteDuration](fromString, DurationConvert.fromDuration)
}
}

/**
* Trait containing `ConfigConvert` instances for Typesafe config models.
*/
trait TypesafeConfigConverters extends ConvertHelpers {

implicit val configConfigConvert: ConfigConvert[Config] = new ConfigConvert[Config] {
override def from(config: ConfigValue): Either[ConfigReaderFailures, Config] = config match {
case co: ConfigObject => Right(co.toConfig)
case other => fail(WrongType(other.valueType().toString, "ConfigObject", ConfigValueLocation(config), None))
}
override def to(t: Config): ConfigValue = t.root()
}

implicit val configObjectConfigConvert: ConfigConvert[ConfigObject] = new ConfigConvert[ConfigObject] {
override def from(config: ConfigValue): Either[ConfigReaderFailures, ConfigObject] = config match {
case c: ConfigObject => Right(c)
case other => fail(WrongType(other.valueType().toString, "ConfigObject", ConfigValueLocation(config), None))
}
override def to(t: ConfigObject): ConfigValue = t
}

implicit val configValueConfigConvert: ConfigConvert[ConfigValue] = new ConfigConvert[ConfigValue] {
override def from(config: ConfigValue): Either[ConfigReaderFailures, ConfigValue] = Right(config)
override def to(t: ConfigValue): ConfigValue = t
}
implicit val configListConfigConvert: ConfigConvert[ConfigList] = new ConfigConvert[ConfigList] {
override def from(config: ConfigValue): Either[ConfigReaderFailures, ConfigList] = config match {
case c: ConfigList => Right(c)
case other => fail(WrongType(other.valueType().toString, "ConfigList", ConfigValueLocation(config), None))
}
override def to(t: ConfigList): ConfigValue = t
}
}

/**
* Trait containing `ConfigConvert` instances for primitive types and simple classes in Java and Scala standard
* libraries.
*/
trait BasicConverters
extends PrimitiveConverters
with UriAndPathConverters
with JavaTimeConverters
with DurationConverters
with TypesafeConfigConverters

object BasicConverters extends BasicConverters

0 comments on commit 721603b

Please sign in to comment.