From 081c5e014697a7c40c63f6815e8e13e976b831ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Fromentin?= Date: Wed, 11 Sep 2024 17:55:30 +0200 Subject: [PATCH] dev: Add BigInt support --- .../github/iltotore/iron/constraint/numeric.scala | 13 ++++++++++++- .../github/iltotore/iron/macros/ReflectUtil.scala | 11 ++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/main/src/io/github/iltotore/iron/constraint/numeric.scala b/main/src/io/github/iltotore/iron/constraint/numeric.scala index 1b0865d..6af3d9c 100644 --- a/main/src/io/github/iltotore/iron/constraint/numeric.scala +++ b/main/src/io/github/iltotore/iron/constraint/numeric.scala @@ -3,7 +3,10 @@ package io.github.iltotore.iron.constraint import io.github.iltotore.iron.constraint.any.* import io.github.iltotore.iron.compileTime.* import io.github.iltotore.iron.{==>, Constraint, Implication} +import io.github.iltotore.iron.macros.reflectUtil +import scala.compiletime.summonInline +import scala.quoted.* import scala.util.NotGiven /** @@ -170,8 +173,16 @@ object numeric: override inline def test(inline value: BigDecimal): Boolean = value > BigDecimal(longValue[V]) inline given [V <: Int | Long]: GreaterConstraint[BigInt, V] with - override inline def test(inline value: BigInt): Boolean = value > BigInt(longValue[V]) + override inline def test(inline value: BigInt): Boolean = ${checkBigInt('value, '{longValue[V]})} + private def checkBigInt(expr: Expr[BigInt], thanExpr: Expr[Long])(using Quotes): Expr[Boolean] = + val rflUtil = reflectUtil + import rflUtil.* + + (expr.decode, thanExpr.decode) match + case (Right(value), Right(than)) => Expr(value > BigInt(than)) + case _ => '{$expr > BigInt($thanExpr)} + given [V1, V2](using V1 > V2 =:= true): (Greater[V1] ==> Greater[V2]) = Implication() given [V1, V2](using V1 > V2 =:= true): (StrictEqual[V1] ==> Greater[V2]) = Implication() diff --git a/main/src/io/github/iltotore/iron/macros/ReflectUtil.scala b/main/src/io/github/iltotore/iron/macros/ReflectUtil.scala index 188ff0d..9061bed 100644 --- a/main/src/io/github/iltotore/iron/macros/ReflectUtil.scala +++ b/main/src/io/github/iltotore/iron/macros/ReflectUtil.scala @@ -182,7 +182,8 @@ class ReflectUtil[Q <: Quotes & Singleton](using val _quotes: Q): private val enhancedDecoders: Map[TypeRepr, (Term, Map[String, ?]) => Either[DecodingFailure, ?]] = Map( TypeRepr.of[Boolean] -> decodeBoolean, - TypeRepr.of[String] -> decodeString + TypeRepr.of[BigInt] -> decodeBigInt, + TypeRepr.of[String] -> decodeString ) /** @@ -325,3 +326,11 @@ class ReflectUtil[Q <: Quotes & Singleton](using val _quotes: Q): case (leftResult, rightResult) => Left(DecodingFailure.StringPartsNotInlined(List(leftResult, rightResult))) case _ => Left(DecodingFailure.Unknown) + + def decodeBigInt(term: Term, definitions: Map[String, ?]): Either[DecodingFailure, BigInt] = + term match + case Apply(Select(Ident("BigInt"), "apply"), List(value)) => + if value.tpe <:< TypeRepr.of[Int] then decodeTerm[Int](value, definitions).map(BigInt.apply) + else if value.tpe <:< TypeRepr.of[Long] then decodeTerm[Long](value, definitions).map(BigInt.apply) + else Left(DecodingFailure.Unknown) + case _ => Left(DecodingFailure.Unknown)