forked from typelevel/doobie
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Instances.scala
66 lines (56 loc) · 1.69 KB
/
Instances.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Copyright (c) 2013-2020 Rob Norris and Contributors
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT
package doobie
package refined
import doobie.util.invariant.*
import eu.timepit.refined.api.RefType
import eu.timepit.refined.api.Validate
import org.tpolecat.typename.*
trait Instances {
implicit def refinedMeta[T, P, F[_, _]](
implicit
metaT: Meta[T],
validate: Validate[T, P],
refType: RefType[F],
manifest: TypeName[F[T, P]],
): Meta[F[T, P]] =
metaT.timap[F[T, P]](
refineType[T, P, F],
)(
unwrapRefinedType[T, P, F],
)
implicit def refinedWrite[T, P, F[_, _]](
implicit
writeT: Write[T],
refType: RefType[F],
): Write[F[T, P]] =
writeT.contramap[F[T, P]](unwrapRefinedType[T, P, F])
implicit def refinedRead[T, P, F[_, _]](
implicit
readT: Read[T],
validate: Validate[T, P],
refType: RefType[F],
manifest: TypeName[F[T, P]],
): Read[F[T, P]] =
readT.map[F[T, P]](refineType[T, P, F])
private def refineType[T, P, F[_, _]](t: T)(
implicit
refType: RefType[F],
validate: Validate[T, P],
manifest: TypeName[F[T, P]],
): F[T, P] =
rightOrException[F[T, P]](refType.refine[P](t)(validate))
private def unwrapRefinedType[T, P, F[_, _]](ftp: F[T, P])(
implicit refType: RefType[F],
): T =
refType.unwrap(ftp)
@SuppressWarnings(Array("org.wartremover.warts.Throw"))
private def rightOrException[T](either: Either[String, T])(
implicit manifest: TypeName[T],
): T =
either match {
case Left(err) => throw new SecondaryValidationFailed[T](err)(manifest)
case Right(t) => t
}
}