fs2.kafka.internal.syntax.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2018-2024 OVO Energy Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
package fs2.kafka.internal
import java.time.temporal.ChronoUnit
import java.time.Duration
import java.util
import java.util.concurrent.TimeUnit
import scala.collection.immutable.SortedSet
import scala.concurrent.duration.FiniteDuration
import cats.{FlatMap, Foldable, Show}
import cats.effect.Async
import cats.syntax.all.*
import fs2.kafka.{Header, Headers, KafkaHeaders}
import fs2.kafka.internal.converters.unsafeWrapArray
import org.apache.kafka.common.KafkaFuture
private[kafka] object syntax {
implicit final class LoggingSyntax[F[_], A](
private val fa: F[A]
) extends AnyVal {
def log(f: A => LogEntry)(implicit
F: FlatMap[F],
logging: Logging[F]
): F[Unit] =
fa.flatMap(a => logging.log(f(a)))
}
implicit final class FiniteDurationSyntax(
private val duration: FiniteDuration
) extends AnyVal {
def toJava: Duration =
if (duration.length == 0L) Duration.ZERO
else
duration.unit match {
case TimeUnit.DAYS => Duration.ofDays(duration.length)
case TimeUnit.HOURS => Duration.ofHours(duration.length)
case TimeUnit.MINUTES => Duration.ofMinutes(duration.length)
case TimeUnit.SECONDS => Duration.ofSeconds(duration.length)
case TimeUnit.MILLISECONDS => Duration.ofMillis(duration.length)
case TimeUnit.MICROSECONDS => Duration.of(duration.length, ChronoUnit.MICROS)
case TimeUnit.NANOSECONDS => Duration.ofNanos(duration.length)
}
}
implicit final class FoldableSyntax[F[_], A](
private val fa: F[A]
) extends AnyVal {
def mkStringAppend(f: (String => Unit, A) => Unit)(
start: String,
sep: String,
end: String
)(implicit F: Foldable[F]): String = {
val builder = new java.lang.StringBuilder(start)
val append: String => Unit = s => { builder.append(s); () }
var first = true
fa.foldLeft(()) { (_, a) =>
if (first) first = false
else builder.append(sep)
f(append, a)
}
builder.append(end).toString
}
def mkStringMap(f: A => String)(start: String, sep: String, end: String)(implicit
F: Foldable[F]
): String = mkStringAppend((append, a) => append(f(a)))(start, sep, end)
def mkString(start: String, sep: String, end: String)(implicit
F: Foldable[F]
): String = mkStringMap(_.toString)(start, sep, end)
def mkStringShow(start: String, sep: String, end: String)(implicit
F: Foldable[F],
A: Show[A]
): String = mkStringMap(_.show)(start, sep, end)
def asJava(implicit F: Foldable[F]): util.List[A] = {
val array = new util.ArrayList[A](fa.size.toInt)
fa.foldLeft(()) { (_, a) => array.add(a); () }
util.Collections.unmodifiableList(array)
}
}
implicit final class MapSyntax[K, V](
private val map: Map[K, V]
) extends AnyVal {
def keySetStrict: Set[K] = {
val builder = Set.newBuilder[K]
map.foreach(builder += _._1)
builder.result()
}
def filterKeysStrict(p: K => Boolean): Map[K, V] = {
val builder = Map.newBuilder[K, V]
map.foreach(e => if (p(e._1)) builder += e)
builder.result()
}
def filterKeysStrictList(p: K => Boolean): List[(K, V)] = {
val builder = List.newBuilder[(K, V)]
map.foreach(e => if (p(e._1)) builder += e)
builder.result()
}
def filterKeysStrictValuesList(p: K => Boolean): List[V] = {
val builder = List.newBuilder[V]
map.foreach(e => if (p(e._1)) builder += e._2)
builder.result()
}
def updatedIfAbsent(k: K, v: => V): Map[K, V] =
if (map.contains(k)) map else map.updated(k, v)
}
implicit final class MapWrappedValueSyntax[F[_], K, V](
private val map: Map[K, F[V]]
) extends AnyVal {
import fs2.kafka.internal.converters.collection.*
def asJavaMap(implicit F: Foldable[F]): util.Map[K, util.Collection[V]] =
map.map { case (k, fv) => k -> (fv.asJava: util.Collection[V]) }.asJava
}
implicit final class JavaUtilCollectionSyntax[A](
private val collection: util.Collection[A]
) extends AnyVal {
def toSet: Set[A] = {
val builder = Set.newBuilder[A]
val it = collection.iterator()
while (it.hasNext) builder += it.next()
builder.result()
}
def toList: List[A] = {
val builder = List.newBuilder[A]
val it = collection.iterator()
while (it.hasNext) builder += it.next()
builder.result()
}
def toVector: Vector[A] = {
val builder = Vector.newBuilder[A]
val it = collection.iterator()
while (it.hasNext) builder += it.next()
builder.result()
}
def mapToList[B](f: A => B): List[B] = {
val builder = List.newBuilder[B]
val it = collection.iterator()
while (it.hasNext) builder += f(it.next())
builder.result()
}
def toSortedSet(implicit ordering: Ordering[A]): SortedSet[A] = {
val builder = SortedSet.newBuilder[A]
val it = collection.iterator()
while (it.hasNext) builder += it.next()
builder.result()
}
}
implicit final class JavaUtilMapSyntax[K, V](
private val map: util.Map[K, V]
) extends AnyVal {
def toMap: Map[K, V] = {
var result = Map.empty[K, V]
val it = map.entrySet.iterator()
while (it.hasNext) {
val e = it.next()
result = result.updated(e.getKey, e.getValue)
}
result
}
def toMapOptionValues: Map[K, Option[V]] = {
var result = Map.empty[K, Option[V]]
val it = map.entrySet.iterator()
while (it.hasNext) {
val e = it.next()
result = result.updated(e.getKey, Option(e.getValue))
}
result
}
}
implicit final class KafkaFutureSyntax[F[_], A](
private val futureF: F[KafkaFuture[A]]
) extends AnyVal {
def cancelable_(implicit F: Async[F]): F[A] =
F.fromCompletionStage(futureF.map(_.toCompletionStage))
}
implicit final class KafkaHeadersSyntax(
private val headers: KafkaHeaders
) extends AnyVal {
def asScala: Headers =
Headers.fromSeq {
unsafeWrapArray {
headers
.toArray
.map { header =>
Header(header.key, header.value)
}
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy