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

just.semver.AdditionalInfo.scala Maven / Gradle / Ivy

package just.semver

import just.Common._

/** @author Kevin Lee
  * @since 2018-10-21
  */
object AdditionalInfo extends Compat {

  import Anh._

  final case class PreRelease(identifier: List[Dsv])
  object PreRelease {
    implicit final class PreReleaseOps(private val preRelease: PreRelease) extends AnyVal {
      @inline def render: String = PreRelease.render(preRelease)
    }
    def render(preRelease: PreRelease): String =
      preRelease.identifier.map(Dsv.render).mkString(".")
  }

  final case class BuildMetaInfo(identifier: List[Dsv])
  object BuildMetaInfo {
    implicit final class BuildMetaInfoOps(private val buildMetaInfo: BuildMetaInfo) extends AnyVal {
      @inline def render: String = BuildMetaInfo.render(buildMetaInfo)
    }
    def render(buildMetaInfo: BuildMetaInfo): String =
      buildMetaInfo.identifier.map(Dsv.render).mkString(".")
  }

  def parsePreRelease(value: String): Either[AdditionalInfoParseError, Option[PreRelease]] =
    parse(
      value,
      {
        case a @ Dsv(Num(n) :: Nil) =>
          if ((n === "0") || n.takeWhile(_ === '0').length === 0)
            Right(a)
          else
            Left(AdditionalInfoParseError.leadingZeroNumError(n))
        case a @ Dsv(_) =>
          Right(a)
      }
    ).map(_.map(PreRelease.apply))

  def parseBuildMetaInfo(value: String): Either[AdditionalInfoParseError, Option[BuildMetaInfo]] =
    parse(value, Right.apply).map(_.map(BuildMetaInfo.apply))

  def parse(
    value: String,
    validator: Dsv => Either[AdditionalInfoParseError, Dsv]
  ): Either[AdditionalInfoParseError, Option[List[Dsv]]] = {
    val alphaNumHyphens: Either[AdditionalInfoParseError, List[Dsv]] =
      Option(value)
        .map(_.split("\\."))
        .map(_.map(Dsv.parse)) match {
        case Some(preRelease) =>
          preRelease.foldRight(List.empty[Dsv].asRight[AdditionalInfoParseError]) { (x, acc) =>
            x.left
              .map {
                case Dsv.DsvParseError.InvalidAlphaNumHyphenError(c, rest) =>
                  AdditionalInfoParseError.invalidAlphaNumHyphenError(c, rest)
                case Dsv.DsvParseError.EmptyAlphaNumHyphenError =>
                  AdditionalInfoParseError.emptyAlphaNumHyphenError
              }
              .flatMap(validator) match {
              case Right(alp) =>
                acc.map(alps => alp :: alps)
              case Left(error) =>
                error.asLeft[List[Dsv]]
            }
          }
        case None =>
          List.empty[Dsv].asRight[AdditionalInfoParseError]
      }
    alphaNumHyphens.map {
      case Nil =>
        none[List[Dsv]]
      case xs =>
        xs.some
    }
  }

  sealed trait AdditionalInfoParseError
  object AdditionalInfoParseError {
    final case class LeadingZeroNumError(n: String) extends AdditionalInfoParseError

    final case class InvalidAlphaNumHyphenError(c: Char, rest: List[Char]) extends AdditionalInfoParseError
    case object EmptyAlphaNumHyphenError extends AdditionalInfoParseError

    def leadingZeroNumError(n: String): AdditionalInfoParseError = LeadingZeroNumError(n)

    def invalidAlphaNumHyphenError(c: Char, rest: List[Char]): AdditionalInfoParseError =
      InvalidAlphaNumHyphenError(c, rest)

    def emptyAlphaNumHyphenError: AdditionalInfoParseError = EmptyAlphaNumHyphenError
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy