Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add deprecation to .refine, introduce .refineUnsafe instead #204

Merged
merged 3 commits into from
Jan 8, 2024
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ log(1.0) //Automatically verified at compile time.
log(-1.0) //Compile-time error: Should be strictly positive

val runtimeValue: Double = ???
log(runtimeValue.refine) //Explicitly refine your external values at runtime.
log(runtimeValue.refineUnsafe) //Explicitly refine your external values at runtime.

runtimeValue.refineEither.map(log) //Use monadic style for functional validation
runtimeValue.refineEither[Positive].map(log) //More explicitly
Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/modules/cats.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ import io.github.iltotore.iron.constraint.all.*
//}
import io.github.iltotore.iron.cats.given

val name1: String :| Alphanumeric = "Martin".refine
val name1: String :| Alphanumeric = "Martin".refineUnsafe
val name2: String :| Alphanumeric = "George"
val age1: Int :| Greater[0] = 60

Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ case class User(age: Int :| Positive)
```scala sc-compile-with:BetterUser.scala
User(1) //Compiles
User(-1) //Does not compile
User(-1.refine) //Compiles but fails at runtime. Useful for runtime checks such as form validation.
User(-1.refineUnsafe) //Compiles but fails at runtime. Useful for runtime checks such as form validation.
//See also `refineOption` and `refineEither`
```

Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/reference/refinement.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ You can imperatively refine a value at runtime (much like an assertion) using th

```scala
val runtimeString: String = ???
val username: String :| Alphanumeric = runtimeString.refine //or more explicitly, refine[LowerCase].
val username: String :| Alphanumeric = runtimeString.refineUnsafe //or more explicitly, refineUnsafe[LowerCase].
```

The `refine` extension method tests the constraint at runtime, throwing an `IllegalArgumentException` if the value
Expand Down
16 changes: 14 additions & 2 deletions main/src/io/github/iltotore/iron/conversion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,22 @@ extension [A, C1](value: A :| C1)
* @param constraint the new constraint to test.
* @return this value refined with `C1 & C2`.
* @throws an [[IllegalArgumentException]] if the constraint is not satisfied.
* @see [[refine]].
* @see [[refineUnsafe]].
*/
@deprecated("Use refineFurtherUnsafe instead. refineFurther will be removed in 3.0")
inline def refineFurther[C2](using inline constraint: Constraint[A, C2]): A :| (C1 & C2) =
(value: A).refine[C2].assumeFurther[C1]
refineFurtherUnsafe[C2]

/**
* Refine the given value again at runtime.
*
* @param constraint the new constraint to test.
* @return this value refined with `C1 & C2`.
* @throws an [[IllegalArgumentException]] if the constraint is not satisfied.
* @see [[refineUnsafe]].
*/
inline def refineFurtherUnsafe[C2](using inline constraint: Constraint[A, C2]): A :| (C1 & C2) =
(value: A).refineUnsafe[C2].assumeFurther[C1]

/**
* Refine the given value again at runtime, resulting in an [[Either]].
Expand Down
22 changes: 17 additions & 5 deletions main/src/io/github/iltotore/iron/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ object IronType:
* @tparam A the refined type.
* @tparam C the constraint applied to the type.
* @return the given value typed as [[IronType]].
* @note this does not check if the constraint is satisfied. Use [[package.refine]] to refine a value at runtime.
* @see [[package.autoRefine]], [[package.refine]], [[package.refineEither]], [[package.refineOption]]
* @note this does not check if the constraint is satisfied. Use [[package.refineUnsafe]] to refine a value at runtime.
* @see [[package.autoRefine]], [[package.refineUnsafe]], [[package.refineEither]], [[package.refineOption]]
*/
inline def apply[A, C](value: A): IronType[A, C] = value

Expand All @@ -52,7 +52,7 @@ extension [A](value: A)
*
* @param constraint the constraint to test with the value to refine.
* @return a constrained value, without performing constraint checks.
* @see [[autoRefine]], [[refine]].
* @see [[autoRefine]], [[refineUnsafe]].
*/
inline def assume[B]: A :| B = value

Expand All @@ -64,7 +64,19 @@ extension [A](value: A)
* @throws an [[IllegalArgumentException]] if the constraint is not satisfied.
* @see [[autoRefine]], [[refineEither]], [[refineOption]].
*/
@deprecated("Use refineUnsafe instead. refine will be removed in 3.0.0")
inline def refine[B](using inline constraint: Constraint[A, B]): A :| B =
refineUnsafe[B]

/**
* Refine the given value at runtime.
*
* @param constraint the constraint to test with the value to refine.
* @return this value as [[IronType]].
* @throws an [[IllegalArgumentException]] if the constraint is not satisfied.
* @see [[autoRefine]], [[refineEither]], [[refineOption]].
*/
inline def refineUnsafe[B](using inline constraint: Constraint[A, B]): A :| B =
if constraint.test(value) then value
else throw IllegalArgumentException(constraint.message)

Expand All @@ -73,7 +85,7 @@ extension [A](value: A)
*
* @param constraint the constraint to test with the value to refine.
* @return a [[Right]] containing this value as [[IronType]] or a [[Left]] containing the constraint message.
* @see [[autoRefine]], [[refine]], [[refineOption]].
* @see [[autoRefine]], [[refineUnsafe]], [[refineOption]].
*/
inline def refineEither[B](using inline constraint: Constraint[A, B]): Either[String, A :| B] =
Either.cond(constraint.test(value), value, constraint.message)
Expand All @@ -83,7 +95,7 @@ extension [A](value: A)
*
* @param constraint the constraint to test with the value to refine.
* @return an Option containing this value as [[IronType]] or [[None]].
* @see [[autoRefine]], [[refine]], [[refineEither]].
* @see [[autoRefine]], [[refineUnsafe]], [[refineEither]].
*/
inline def refineOption[B](using inline constraint: Constraint[A, B]): Option[A :| B] =
Option.when(constraint.test(value))(value)
Loading