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

medeia.decoder.BsonKeyDecoder.scala Maven / Gradle / Ivy

The newest version!
package medeia.decoder

import java.util.UUID
import cats.Functor
import cats.syntax.either._
import cats.data.EitherNec
import medeia.decoder.BsonDecoderError.{FieldParseError, GenericDecoderError}
import java.util.Locale
import java.util.IllformedLocaleException

trait BsonKeyDecoder[A] { self =>
  def decode(key: String): EitherNec[BsonDecoderError, A]

  def map[B](f: A => B): BsonKeyDecoder[B] = (key: String) => self.decode(key).map(f)

  def emap[B](f: A => Either[String, B]): BsonKeyDecoder[B] =
    (key: String) => self.decode(key).flatMap(f(_).leftMap(GenericDecoderError(_)).toEitherNec)
}

object BsonKeyDecoder extends DefaultBsonKeyDecoderInstances {
  def apply[A: BsonKeyDecoder]: BsonKeyDecoder[A] = implicitly

  def decode[A: BsonKeyDecoder](key: String): EitherNec[BsonDecoderError, A] = {
    BsonKeyDecoder[A].decode(key)
  }

  implicit val bsonKeyDecoderFunctor: Functor[BsonKeyDecoder] = new Functor[BsonKeyDecoder] {
    override def map[A, B](fa: BsonKeyDecoder[A])(f: A => B): BsonKeyDecoder[B] = fa.map(f)
  }
}

trait DefaultBsonKeyDecoderInstances {
  implicit val stringDecoder: BsonKeyDecoder[String] = key => Right(key)

  implicit val intDecoder: BsonKeyDecoder[Int] = key =>
    Either.catchOnly[NumberFormatException](key.toInt).leftMap(FieldParseError("Cannot parse int", _)).toEitherNec

  implicit val longDecoder: BsonKeyDecoder[Long] = key =>
    Either.catchOnly[NumberFormatException](key.toLong).leftMap(FieldParseError("Cannot parse long", _)).toEitherNec

  implicit val doubleDecoder: BsonKeyDecoder[Double] = key =>
    Either.catchOnly[NumberFormatException](key.toDouble).leftMap(FieldParseError("Cannot parse double", _)).toEitherNec

  implicit val uuidDecoder: BsonKeyDecoder[UUID] = key =>
    Either.catchOnly[IllegalArgumentException](UUID.fromString(key)).leftMap(FieldParseError("Cannot parse UUID", _)).toEitherNec

  implicit val localeDecoder: BsonKeyDecoder[Locale] = key =>
    Either
      .catchOnly[IllformedLocaleException](new Locale.Builder().setLanguageTag(key).build())
      .leftMap(FieldParseError("Cannot parse locale", _))
      .toEitherNec
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy