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

zhttp.http.PathModule.scala Maven / Gradle / Ivy

There is a newer version: 2.0.0-RC11
Show newest version
package zhttp.http

import scala.annotation.tailrec

private[zhttp] trait PathModule { module =>
  val !! : Path = Path.End

  sealed trait Path { self =>
    final override def toString: String = this.encode

    final def /(name: String): Path = Path(self.toList :+ name)

    final def /:(name: String): Path = append(name)

    final def append(name: String): Path = if (name.isEmpty) self else Path.Cons(name, self)

    final def drop(n: Int): Path = Path(self.toList.drop(n))

    final def dropLast(n: Int): Path = Path(self.toList.reverse.drop(n).reverse)

    final def encode: String = {
      @tailrec
      def loop(self: Path, str: String): String = {
        self match {
          case Path.End              => str
          case Path.Cons(name, path) => loop(path, s"$str/$name")
        }
      }
      val res                                   = loop(self, "")
      if (res.isEmpty) "/" else res
    }

    final def initial: Path = self match {
      case Path.End           => self
      case Path.Cons(_, path) => path
    }

    final def isEnd: Boolean = self match {
      case Path.End        => true
      case Path.Cons(_, _) => false
    }

    final def last: Option[String] = self match {
      case Path.End           => None
      case Path.Cons(name, _) => Option(name)
    }

    final def reverse: Path = Path(toList.reverse)

    @tailrec
    final def startsWith(other: Path): Boolean = {
      if (self == other) true
      else
        (self, other) match {
          case (/(p1, _), p2) => p1.startsWith(p2)
          case _              => false

        }
    }

    final def take(n: Int): Path = Path(self.toList.take(n))

    def toList: List[String]
  }

  object Path {
    def apply(): Path                   = End
    def apply(string: String): Path     = if (string.trim.isEmpty) End else Path(string.split("/").toList)
    def apply(seqString: String*): Path = Path(seqString.toList)
    def apply(list: List[String]): Path = list.foldRight[Path](End)((s, a) => a.append(s))

    def empty: Path = End

    def unapplySeq(arg: Path): Option[List[String]] = Option(arg.toList)

    case class Cons(name: String, path: Path) extends Path {
      override def toList: List[String] = name :: path.toList
    }

    case object End extends Path {
      override def toList: List[String] = Nil
    }
  }

  object /: {
    def unapply(path: Path): Option[(String, Path)] =
      path match {
        case Path.End              => None
        case Path.Cons(name, path) => Option(name -> path)
      }
  }

  object / {
    def unapply(path: Path): Option[(Path, String)] = {
      path.toList.reverse match {
        case Nil          => None
        case head :: next => Option((Path(next.reverse), head))
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy