Skip to content

Commit

Permalink
Close #215 - Add refined4s-extras-render to support Render for refined4s
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-lee committed Jan 1, 2024
1 parent 605b66f commit 1feeb22
Show file tree
Hide file tree
Showing 7 changed files with 1,426 additions and 0 deletions.
13 changes: 13 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ lazy val doobieCe3 = module("doobie-ce3", crossProject(JVMPlatform, JSPlatfor
lazy val doobieCe3Jvm = doobieCe3.jvm
lazy val doobieCe3Js = doobieCe3.js.settings(jsSettingsForFuture)

lazy val extrasRender = module("extras-render", crossProject(JVMPlatform, JSPlatform))
.settings(
libraryDependencies ++= List(
libs.extrasRender
)
)
.dependsOn(
core % props.IncludeTest
)
lazy val extrasRenderJvm = extrasRender.jvm
lazy val extrasRenderJs = extrasRender.js.settings(jsSettingsForFuture)

lazy val docs = (project in file("docs-gen-tmp/docs"))
.enablePlugins(MdocPlugin, DocusaurPlugin)
.settings(
Expand Down Expand Up @@ -254,6 +266,7 @@ lazy val libs = new {
lazy val extrasHedgehogCirce = "io.kevinlee" %% "extras-hedgehog-circe" % props.ExtrasVersion
lazy val extrasDoobieToolsCe2 = "io.kevinlee" %% "extras-doobie-tools-ce2" % props.ExtrasVersion
lazy val extrasDoobieToolsCe3 = "io.kevinlee" %% "extras-doobie-tools-ce3" % props.ExtrasVersion
lazy val extrasRender = "io.kevinlee" %% "extras-render" % props.ExtrasVersion

lazy val cats = "org.typelevel" %% "cats-core" % props.CatsVersion

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package refined4s.modules.extras.derivation

import extras.render.Render
import refined4s.NewtypeBase

/** @author Kevin Lee
* @since 2024-01-01
*/
trait ExtrasRender[A: Render] {
self: NewtypeBase[A] =>

given derivedRender: Render[Type] = deriving[Render]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package refined4s.modules.extras.derivation.generic

import refined4s.*
import extras.render.Render

/** @author Kevin Lee
* @since 2024-01-01
*/
object auto {

/** `Render` instance for Newtype, Refined and InlinedRefined types that delegates from the `Render`
* instance of the base type.
*/
inline given derivedRender[A, B](using coercible: Coercible[A, B], renderB: Render[B]): Render[A] =
renderB.contramap[A](coercible(_))

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package refined4s.modules.extras.derivation.types

import extras.render.Render

import refined4s.types.all.*

/** @author Kevin Lee
* @since 2024-01-01
*/
trait all {

inline given derivedNegIntRender(using renderActual: Render[Int]): Render[NegInt] = renderActual.contramap(_.value)

inline given derivedNonNegIntRender(using renderActual: Render[Int]): Render[NonNegInt] =
renderActual.contramap(_.value)

inline given derivedPosIntRender(using renderActual: Render[Int]): Render[PosInt] = renderActual.contramap(_.value)

inline given derivedNonPosIntRender(using renderActual: Render[Int]): Render[NonPosInt] =
renderActual.contramap(_.value)

inline given derivedNegLongRender(using renderActual: Render[Long]): Render[NegLong] = renderActual.contramap(_.value)

inline given derivedNonNegLongRender(using renderActual: Render[Long]): Render[NonNegLong] =
renderActual.contramap(_.value)

inline given derivedPosLongRender(using renderActual: Render[Long]): Render[PosLong] = renderActual.contramap(_.value)

inline given derivedNonPosLongRender(using renderActual: Render[Long]): Render[NonPosLong] =
renderActual.contramap(_.value)

inline given derivedNegShortRender(using renderActual: Render[Short]): Render[NegShort] =
renderActual.contramap(_.value)

inline given derivedNonNegShortRender(using renderActual: Render[Short]): Render[NonNegShort] =
renderActual.contramap(_.value)

inline given derivedPosShortRender(using renderActual: Render[Short]): Render[PosShort] =
renderActual.contramap(_.value)

inline given derivedNonPosShortRender(using renderActual: Render[Short]): Render[NonPosShort] =
renderActual.contramap(_.value)

inline given derivedNegByteRender(using renderActual: Render[Byte]): Render[NegByte] = renderActual.contramap(_.value)

inline given derivedNonNegByteRender(using renderActual: Render[Byte]): Render[NonNegByte] =
renderActual.contramap(_.value)

inline given derivedPosByteRender(using renderActual: Render[Byte]): Render[PosByte] = renderActual.contramap(_.value)

inline given derivedNonPosByteRender(using renderActual: Render[Byte]): Render[NonPosByte] =
renderActual.contramap(_.value)

inline given derivedNegFloatRender(using renderActual: Render[Float]): Render[NegFloat] =
renderActual.contramap(_.value)

inline given derivedNonNegFloatRender(using renderActual: Render[Float]): Render[NonNegFloat] =
renderActual.contramap(_.value)

inline given derivedPosFloatRender(using renderActual: Render[Float]): Render[PosFloat] =
renderActual.contramap(_.value)

inline given derivedNonPosFloatRender(using renderActual: Render[Float]): Render[NonPosFloat] =
renderActual.contramap(_.value)

inline given derivedNegDoubleRender(using renderActual: Render[Double]): Render[NegDouble] =
renderActual.contramap(_.value)

inline given derivedNonNegDoubleRender(using renderActual: Render[Double]): Render[NonNegDouble] =
renderActual.contramap(_.value)

inline given derivedPosDoubleRender(using renderActual: Render[Double]): Render[PosDouble] =
renderActual.contramap(_.value)

inline given derivedNonPosDoubleRender(using renderActual: Render[Double]): Render[NonPosDouble] =
renderActual.contramap(_.value)

inline given derivedNegBigIntRender(using renderActual: Render[BigInt]): Render[NegBigInt] =
renderActual.contramap(_.value)

inline given derivedNonNegBigIntRender(using renderActual: Render[BigInt]): Render[NonNegBigInt] =
renderActual.contramap(_.value)

inline given derivedPosBigIntRender(using renderActual: Render[BigInt]): Render[PosBigInt] =
renderActual.contramap(_.value)

inline given derivedNonPosBigIntRender(using renderActual: Render[BigInt]): Render[NonPosBigInt] =
renderActual.contramap(_.value)

inline given derivedNegBigDecimalRender(using renderActual: Render[BigDecimal]): Render[NegBigDecimal] =
renderActual.contramap(_.value)

inline given derivedNonNegBigDecimalRender(using renderActual: Render[BigDecimal]): Render[NonNegBigDecimal] =
renderActual.contramap(_.value)

inline given derivedPosBigDecimalRender(using renderActual: Render[BigDecimal]): Render[PosBigDecimal] =
renderActual.contramap(_.value)

inline given derivedNonPosBigDecimalRender(using renderActual: Render[BigDecimal]): Render[NonPosBigDecimal] =
renderActual.contramap(_.value)

// strings

inline given derivedNonEmptyStringRender(using renderActual: Render[String]): Render[NonEmptyString] =
renderActual.contramap(_.value)

// network

inline given derivedUriRender(using renderActual: Render[String]): Render[Uri] = renderActual.contramap(_.value)

inline given derivedPortNumberRender(using renderActual: Render[Int]): Render[PortNumber] =
renderActual.contramap(_.value)

inline given derivedSystemPortNumberRender(using renderActual: Render[Int]): Render[SystemPortNumber] =
renderActual.contramap(_.value)

inline given derivedNonSystemPortNumberRender(using renderActual: Render[Int]): Render[NonSystemPortNumber] =
renderActual.contramap(_.value)

inline given derivedUserPortNumberRender(using renderActual: Render[Int]): Render[UserPortNumber] =
renderActual.contramap(_.value)

inline given derivedDynamicPortNumberRender(using renderActual: Render[Int]): Render[DynamicPortNumber] =
renderActual.contramap(_.value)

}
object all extends all
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package refined4s.modules.extras.derivation

import extras.render.*
import extras.render.syntax.*
import hedgehog.*
import hedgehog.runner.*
import refined4s.*
import refined4s.modules.extras.derivation.*

/** @author Kevin Lee
* @since 2024-01-01
*/
object ExtrasRenderSpec extends Properties {
override def tests: List[Test] = List(
property(
"Given Newtype with ExtrasRender. Newtype[A].render(a) should return the same String as Render[A].render(a)",
testRenderNewtype,
),
property(
"Given Refined with ExtrasRender. Refined[A].render(a) should return the same String as Render[A].render(a)",
testRenderRefined,
),
property(
"Given Newtype[Refined] with ExtrasRender. Newtype[Refined[A]].render(a) should return the same String as Render[A].render(a)",
testRenderNewtypeRefined,
),
)

def testRenderNewtype: Property =
for {
s <- Gen.string(Gen.unicode, Range.linear(0, 10)).log("s")
} yield {
val a = MyNewtype(s)
a.render ==== Render[String].render(s)
}

def testRenderRefined: Property =
for {
s <- Gen.string(Gen.unicode, Range.linear(1, 10)).log("s")
} yield {
val a = MyRefinedType.unsafeFrom(s)
a.render ==== Render[String].render(s)
}

def testRenderNewtypeRefined: Property =
for {
s <- Gen.string(Gen.unicode, Range.linear(1, 10)).log("s")
} yield {
val a = MyRefinedNewtype(MyRefinedType.unsafeFrom(s))
a.render ==== Render[String].render(s)
}

type MyNewtype = MyNewtype.Type
object MyNewtype extends Newtype[String] with ExtrasRender[String]

type MyRefinedType = MyRefinedType.Type
@SuppressWarnings(Array("org.wartremover.warts.Equals"))
object MyRefinedType extends Refined[String] with ExtrasRender[String] {
override inline def invalidReason(a: String): String =
"It has to be a non-empty String but got \"" + a + "\""

override inline def predicate(a: String): Boolean = a != ""
}

type MyRefinedNewtype = MyRefinedNewtype.Type
object MyRefinedNewtype extends Newtype[MyRefinedType] with ExtrasRender[MyRefinedType]

}
Loading

0 comments on commit 1feeb22

Please sign in to comment.