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

smithy4s.http.internals.package.scala Maven / Gradle / Ivy

There is a newer version: 0.19.0-41-91762fb
Show newest version
/*
 *  Copyright 2021-2024 Disney Streaming
 *
 *  Licensed under the Tomorrow Open Source Technology License, Version 1.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     https://disneystreaming.github.io/TOST-1.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package smithy4s
package http

package object internals {

  private[internals] type AwsMergeableHeader[A] = Option[A => String]
  private[internals] type AwsHeaderSplitter[A] = Option[String => Seq[String]]
  private[http] type HttpCode[A] = A => Option[Int]
  private[http] val httpHints = HintMask(HttpBinding)

  private[internals] type HostPrefixEncoder[A] =
    smithy4s.codecs.Writer[List[String], A]
  private[internals] type MaybeHostPrefixEncoder[A] =
    Option[HostPrefixEncoder[A]]

  private[internals] implicit class vectorOps[A](val vector: Vector[A])
      extends AnyVal {
    def traverse[B](f: A => Option[B]): Option[Vector[B]] =
      vector.foldLeft[Option[Vector[B]]](Some(Vector.empty)) { (result, a) =>
        for {
          acc <- result
          b <- f(a)
        } yield (acc.:+(b))
      }

    def traverse[E, B](f: A => Either[E, B]): Either[E, Vector[B]] =
      vector.foldLeft[Either[E, Vector[B]]](Right(Vector.empty)) {
        (result, a) =>
          for {
            acc <- result
            b <- f(a)
          } yield (acc.:+(b))
      }
  }

  private[internals] implicit class listOps[A](val list: List[A])
      extends AnyVal {
    def traverse[B](f: A => Option[B]): Option[List[B]] =
      list.foldLeft[Option[List[B]]](Some(List.empty)) { (result, a) =>
        for {
          acc <- result
          b <- f(a)
        } yield (acc.:+(b))
      }
  }

  private[http] def pathSegments(
      str: String
  ): Option[Vector[PathSegment]] = {
    str
      .split('?')
      .head
      .split('/')
      .toVector
      .filterNot(_.isEmpty())
      .traverse(fromToString(_))

  }

  private[http] def staticQueryParams(
      uri: String
  ): Map[String, Seq[String]] = {
    uri.split("\\?", 2) match {
      case Array(_) => Map.empty
      case Array(_, query) =>
        query.split("&").toList.foldLeft(Map.empty[String, Seq[String]]) {
          case (acc, param) =>
            val (k, v) = param.split("=", 2) match {
              case Array(key)        => (key, "")
              case Array(key, value) => (key, value)
            }
            acc.updated(k, acc.getOrElse(k, Seq.empty) :+ v)
        }
    }
  }

  private def fromToString(str: String): Option[PathSegment] = {
    if (str == null || str.isEmpty) None
    else if (str.startsWith("{") && str.endsWith("+}"))
      Some(PathSegment.greedy(str.substring(1, str.length() - 2)))
    else if (str.startsWith("{") && str.endsWith("}"))
      Some(PathSegment.label(str.substring(1, str.length() - 1)))
    else Some(PathSegment.static(str))
  }

  private[http] def hostPrefixSegments(
      str: String
  ): Vector[HostPrefixSegment] = {
    // example input: "foo.{bar}--{baz}abcd{test}.com" produces the following
    // output: Vector(static(foo.), label(bar), static(--), label(baz), static(abcd), label(test), static(.com))
    str
      .split('{')
      .toList
      .flatMap(_.split("}", 2).toList match {
        case "" :: Nil     => Nil
        case static :: Nil => HostPrefixSegment.static(static) :: Nil
        case label :: "" :: Nil =>
          HostPrefixSegment.label(label) :: Nil
        case label :: static :: Nil =>
          HostPrefixSegment
            .label(label) :: HostPrefixSegment.static(static) :: Nil
        case _ => Nil
      })
      .toVector
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy