forked from ceedubs/ficus
-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ValueReader instances for Either[L,R] (#45)
* eitherReader: valueReader implementation for Either[A,B] given A and B have their own value readers. * eitherReader: minor test utility. * eitherReader: test spec for either. * eitherReader: removed auto generated ide comments * eitherReader: minor fixes according to review comments.
- Loading branch information
1 parent
5609b7f
commit f5f7f57
Showing
3 changed files
with
85 additions
and
1 deletion.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
src/main/scala/net/ceedubs/ficus/readers/EitherReader.scala
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package net.ceedubs.ficus.readers | ||
import com.typesafe.config.{Config, ConfigException} | ||
|
||
trait EitherReader { | ||
implicit def eitherReader[L,R]( implicit lReader : ValueReader[L], rReader : ValueReader[R]) : ValueReader[Either[L,R]] = | ||
new ValueReader[Either[L,R]]{ | ||
/** Reads the value at the path `path` in the Config */ | ||
override def read(config: Config, path: String): Either[L, R] = { | ||
TryReader.tryValueReader(rReader).read( config, path ) | ||
.map( Right(_) ) | ||
.recover{ | ||
case _ : ConfigException => Left( lReader.read(config, path)) | ||
} | ||
.get | ||
} | ||
} | ||
} | ||
|
||
object EitherReader extends EitherReader |
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
63 changes: 63 additions & 0 deletions
63
src/test/scala/net/ceedubs/ficus/readers/EitherReadersSpec.scala
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package net.ceedubs.ficus.readers | ||
|
||
import com.typesafe.config.ConfigFactory | ||
import net.ceedubs.ficus.{ConfigSerializer, Spec} | ||
import net.ceedubs.ficus.ConfigSerializerOps._ | ||
import org.scalacheck.Arbitrary | ||
|
||
import scala.util.{Failure, Try} | ||
import scala.collection.JavaConverters._ | ||
|
||
class EitherReadersSpec extends Spec with EitherReader with OptionReader with AnyValReaders with StringReader with TryReader with CollectionReaders{ | ||
def is=s2""" | ||
An Either value reader should | ||
should read right side when possible $readRightSideString | ||
fallback to left side when key is missing $fallbackToLeftSideOnMissingKey | ||
fallback to left when failing to read right $fallbackToLeftSideOnBadRightValue | ||
fail when both sides fail $rightAndLeftFailure | ||
handle a Try on the right side $rightSideTry | ||
handle a Try on the left side $leftSideTry | ||
handle complex types $handleComplexTypes | ||
""" | ||
|
||
|
||
def readRightSideString = prop{ a : String => | ||
val cfg = a.toConfigValue.atKey("x") | ||
eitherReader[String,String].read(cfg, "x") must beEqualTo(Right(a)) | ||
} | ||
|
||
def fallbackToLeftSideOnMissingKey = prop{ a : String => | ||
eitherReader[Option[String], String].read( ConfigFactory.empty(), "x" ) must beEqualTo( Left(None) ) | ||
} | ||
|
||
def fallbackToLeftSideOnBadRightValue = prop{ a : Int => | ||
val badVal = a.toString + "xx" | ||
eitherReader[String, Int].read( badVal.toConfigValue.atKey("x"), "x" ) must beEqualTo( Left(badVal) ) | ||
} | ||
|
||
def rightAndLeftFailure = prop{ a : Int => | ||
val badVal = a.toString + "xx" | ||
tryValueReader(eitherReader[Int, Int]).read( badVal.toConfigValue.atKey("x"), "x" ) must beAnInstanceOf[Failure[Int]] | ||
} | ||
|
||
def rightSideTry = prop{ a : Int => | ||
val badVal = a.toString + "xx" | ||
eitherReader[Int, Try[Int]].read( a.toConfigValue.atKey("x"), "x" ) must beRight( a ) | ||
eitherReader[Int, Try[Int]].read( badVal.toConfigValue.atKey("x"), "x" ) must beRight( beFailedTry[Int] ) | ||
} | ||
|
||
def leftSideTry = prop{ a : Int => | ||
val badVal = a.toString + "xx" | ||
eitherReader[Try[String], Int].read( badVal.toConfigValue.atKey("x"), "x" ) must beLeft( beSuccessfulTry( badVal) ) | ||
eitherReader[Try[Int], Int].read( badVal.toConfigValue.atKey("x"), "x" ) must beLeft( beFailedTry[Int] ) | ||
} | ||
|
||
def handleComplexTypes = prop{ (a : Int, b : Int ) => | ||
val iMap = Map( "a" -> a, "b" -> b ) | ||
val sMap = Map( "a" -> s"${a}xx", "b" -> s"${b}xx") | ||
|
||
eitherReader[Map[String,String], Map[String,String]].read( sMap.toConfigValue.atKey("a"), "a" ) must beRight(sMap) | ||
eitherReader[Map[String,String], Map[String,Int]].read( iMap.toConfigValue.atKey("a"), "a" ) must beRight(iMap) | ||
eitherReader[Map[String,String], Map[String,Int]].read( sMap.toConfigValue.atKey("a"), "a" ) must beLeft(sMap) | ||
} | ||
} |