blob: 183ad9a428c14a8d005bd3d80337563e6ee400a9 (
plain) (
blame)
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
67
68
69
70
71
72
73
|
package xyz.driver.core
package rest
package directives
import java.time.Instant
import java.util.UUID
import akka.http.scaladsl.model.Uri.Path
import akka.http.scaladsl.server.PathMatcher.{Matched, Unmatched}
import akka.http.scaladsl.server.{PathMatcher, PathMatcher1, PathMatchers => AkkaPathMatchers}
import eu.timepit.refined.collection.NonEmpty
import eu.timepit.refined.refineV
import xyz.driver.core.time.Time
import scala.util.control.NonFatal
/** Akka-HTTP path matchers for custom core types. */
trait PathMatchers {
private def UuidInPath[T]: PathMatcher1[Id[T]] =
AkkaPathMatchers.JavaUUID.map((id: UUID) => Id[T](id.toString.toLowerCase))
def IdInPath[T]: PathMatcher1[Id[T]] = UuidInPath[T] | new PathMatcher1[Id[T]] {
def apply(path: Path) = path match {
case Path.Segment(segment, tail) => Matched(tail, Tuple1(Id[T](segment)))
case _ => Unmatched
}
}
def NameInPath[T]: PathMatcher1[Name[T]] = new PathMatcher1[Name[T]] {
def apply(path: Path) = path match {
case Path.Segment(segment, tail) => Matched(tail, Tuple1(Name[T](segment)))
case _ => Unmatched
}
}
private def timestampInPath: PathMatcher1[Long] =
PathMatcher("""[+-]?\d*""".r) flatMap { string =>
try Some(string.toLong)
catch { case _: IllegalArgumentException => None }
}
def InstantInPath: PathMatcher1[Instant] =
new PathMatcher1[Instant] {
def apply(path: Path): PathMatcher.Matching[Tuple1[Instant]] = path match {
case Path.Segment(head, tail) =>
try Matched(tail, Tuple1(Instant.parse(head)))
catch {
case NonFatal(_) => Unmatched
}
case _ => Unmatched
}
} | timestampInPath.map(Instant.ofEpochMilli)
def TimeInPath: PathMatcher1[Time] = InstantInPath.map(instant => Time(instant.toEpochMilli))
def NonEmptyNameInPath[T]: PathMatcher1[NonEmptyName[T]] = new PathMatcher1[NonEmptyName[T]] {
def apply(path: Path) = path match {
case Path.Segment(segment, tail) =>
refineV[NonEmpty](segment) match {
case Left(_) => Unmatched
case Right(nonEmptyString) => Matched(tail, Tuple1(NonEmptyName[T](nonEmptyString)))
}
case _ => Unmatched
}
}
def RevisionInPath[T]: PathMatcher1[Revision[T]] =
PathMatcher("""[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}""".r) flatMap { string =>
Some(Revision[T](string))
}
}
|