All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.hireproof.structure.Headers.scala Maven / Gradle / Ivy

The newest version!
package io.hireproof.structure

import cats.Invariant
import cats.data.{Chain, Validated}
import cats.syntax.all._
import io.hireproof.screening.Validation
import org.typelevel.ci._

sealed abstract class Headers[A] extends Structure.Product[A] { self =>
  final override type Self[a] = Headers[a]
  final override type Element[a] = Header[a]
  final override type Group[a] = Headers[a]

  def toChain: Chain[Header[_]]

  final override def zipAll[T](headers: Headers[T]): Headers[A |*| T] = new Headers[A |*| T] {
    override def toChain: Chain[Header[_]] = self.toChain ++ headers.toChain
    override def fromStringChain(
        values: Chain[(CIString, String)]
    ): Validated[Errors, (Chain[(CIString, String)], A |*| T)] = self
      .fromStringChain(values)
      .andThen { case (remainders, a) => headers.fromStringChain(remainders).map(_.tupleLeft(a)) }
    override def toStringChain(at: A |*| T): Chain[(CIString, String)] =
      self.toStringChain(at._1) ++ headers.toStringChain(at._2)
  }
  final def zip[T](header: Header[T]): Headers[A |*| T] = zipAll(Headers.fromHeader(header))

  override private[structure] def vimap[T](
      f: A => Validated[Errors, T],
      g: T => A,
      validation: Option[Validation[_, _]]
  ): Headers[T] = new Headers[T] {
    override def toChain: Chain[Header[_]] = self.toChain
    override def fromStringChain(
        headers: Chain[(CIString, String)]
    ): Validated[Errors, (Chain[(CIString, String)], T)] = self.fromStringChain(headers).andThen(_.traverse(f(_)))
    override def toStringChain(t: T): Chain[(CIString, String)] = self.toStringChain(g(t))
  }

  def fromStringChain(headers: Chain[(CIString, String)]): Validated[Errors, (Chain[(CIString, String)], A)]
  def toStringChain(a: A): Chain[(CIString, String)]
}

object Headers {
  val Empty: Headers[Unit] = new Headers[Unit] {
    override def toChain: Chain[Header[_]] = Chain.empty
    override def fromStringChain(
        headers: Chain[(CIString, String)]
    ): Validated[Errors, (Chain[(CIString, String)], Unit)] =
      (headers, ()).valid
    override def toStringChain(a: Unit): Chain[(CIString, String)] = Chain.empty
  }

  def fromHeader[A](header: Header[A]): Headers[A] = new Headers[A] {
    override def toChain: Chain[Header[_]] = Chain.one(header)
    override def fromStringChain(
        headers: Chain[(CIString, String)]
    ): Validated[Errors, (Chain[(CIString, String)], A)] = header.fromStringChain(headers)
    override def toStringChain(a: A): Chain[(CIString, String)] = header.toStringChain(a)
  }

  implicit val invariant: Invariant[Headers] = new Invariant[Headers] {
    override def imap[A, B](fa: Headers[A])(f: A => B)(g: B => A): Headers[B] = fa.imap(f)(g)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy