All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
o-deps.proto-purs_2.11.2.1.3.io.github.zero-deps.proto_sjs1_3.2.1.3.source-code.Common.scala Maven / Gradle / Ivy
package proto
import com.google.protobuf.{CodedOutputStream, CodedInputStream}
import scala.quoted.*
import scala.collection.immutable.ArraySeq
import scala.annotation.*
import compiletime.asMatchable
trait Common:
implicit val qctx: Quotes
import qctx.reflect.{*, given}
import qctx.reflect.defn.*
import report.*
private[proto] case class FieldInfo(
name: String
, num: Int
, sym: Symbol
, tpe: TypeRepr & Matchable
, getter: Term => Term
, sizeSym: Symbol
, prepareSym: Symbol
, prepareOptionSym: Symbol = Symbol.noSymbol
, prepareArraySym: Symbol = Symbol.noSymbol
, defaultValue: Option[Term]
, isCaseObject: Boolean = false
, nonPacked: Boolean = false
):
def tag: Int =
if nonPacked && tpe.isRepeated && tpe.repeatedArgument.asMatchable.isCommonType then
num << 3 | wireType(tpe.repeatedArgument.asMatchable)
else num << 3 | wireType(tpe)
def wireType(t: TypeRepr & Matchable): Int =
if t.isInt || t.isLong || t.isBoolean then 0
else if t.isDouble then 1
else if t.isFloat then 5
else if t.isOption then wireType(t.optionArgument.asMatchable)
else if t.isString ||
t.isArrayByte ||
t.isArraySeqByte ||
t.isCaseType ||
t.isSealedTrait ||
t.isRepeated then 2
else 2
def writeFun(os: Expr[CodedOutputStream], t: TypeRepr & Matchable, getterTerm: Term)(using Quotes): Expr[Unit] =
if t.isInt then '{ ${os}.writeInt32NoTag(${getterTerm.asExprOf[Int]}) }
else if t.isLong then '{ ${os}.writeInt64NoTag(${getterTerm.asExprOf[Long]}) }
else if t.isBoolean then '{ ${os}.writeBoolNoTag(${getterTerm.asExprOf[Boolean]}) }
else if t.isDouble then '{ ${os}.writeDoubleNoTag(${getterTerm.asExprOf[Double]}) }
else if t.isFloat then '{ ${os}.writeFloatNoTag(${getterTerm.asExprOf[Float]}) }
else if t.isString then '{ ${os}.writeStringNoTag(${getterTerm.asExprOf[String]}) }
else if t.isArrayByte then '{ ${os}.writeByteArrayNoTag(${getterTerm.asExprOf[Array[Byte]]}) }
else if t.isArraySeqByte then '{ ${os}.writeByteArrayNoTag(${getterTerm.asExprOf[ArraySeq[Byte]]}.toArray[Byte]) }
else errorAndAbort(s"Unsupported common type: ${t.typeSymbol.name}")
def sizeFun(t: TypeRepr & Matchable, getterTerm: Term): Expr[Int] =
if t.isInt then '{ CodedOutputStream.computeInt32SizeNoTag(${getterTerm.asExprOf[Int]}) }
else if t.isLong then '{ CodedOutputStream.computeInt64SizeNoTag(${getterTerm.asExprOf[Long]}) }
else if t.isBoolean then Expr(1)
else if t.isDouble then Expr(8)
else if t.isFloat then Expr(4)
else if t.isString then '{ CodedOutputStream.computeStringSizeNoTag(${getterTerm.asExprOf[String]}) }
else if t.isArrayByte then '{ CodedOutputStream.computeByteArraySizeNoTag(${getterTerm.asExprOf[Array[Byte]]}) }
else if t.isArraySeqByte then '{ CodedOutputStream.computeByteArraySizeNoTag(${getterTerm.asExprOf[ArraySeq[Byte]]}.toArray[Byte]) }
else errorAndAbort(s"Unsupported common type: ${t.typeSymbol.name}")
def readFun(t: TypeRepr & Matchable, is: Expr[CodedInputStream])(using Quotes): Term =
if t.isInt then '{ ${is}.readInt32 }.asTerm
else if t.isLong then '{ ${is}.readInt64 }.asTerm
else if t.isBoolean then '{ ${is}.readBool }.asTerm
else if t.isDouble then '{ ${is}.readDouble }.asTerm
else if t.isFloat then '{ ${is}.readFloat }.asTerm
else if t.isString then '{ ${is}.readString.nn }.asTerm
else if t.isArrayByte then '{ ${is}.readByteArray.nn }.asTerm
else if t.isArraySeqByte then '{ ArraySeq.unsafeWrapArray(${is}.readByteArray.nn) }.asTerm
else errorAndAbort(s"Unsupported common type: ${t.typeSymbol.name}")
val ArrayByteType: TypeRepr = TypeRepr.of[Array[Byte]]
val ArraySeqByteType: TypeRepr = TypeRepr.of[ArraySeq[Byte]]
val NTpe: TypeRepr = TypeRepr.of[N]
val RestrictedNType: TypeRepr = TypeRepr.of[RestrictedN]
val ItetableType: TypeRepr = TypeRepr.of[scala.collection.Iterable[?]]
val ArrayType: TypeRepr = TypeRepr.of[Array[?]]
val PrepareType: TypeRepr = TypeRepr.of[Prepare]
val CodedInputStreamType: TypeRepr = TypeRepr.of[CodedInputStream]
extension (s: Symbol)
def constructorParams: List[Symbol] = s.primaryConstructor.paramSymss.find(_.headOption.fold(false)( _.isTerm)).getOrElse(Nil)
def tpe: TypeRepr =
s.tree match
case x: ClassDef => x.constructor.returnTpt.tpe
case ValDef(_,tpt,_) => tpt.tpe
case Bind(_, pattern: Term) => pattern.tpe
def unitLiteral: Literal = Literal(UnitConstant())
def defaultMethodName(i: Int): String = s"$$lessinit$$greater$$default$$${i+1}"
def unitExpr: Expr[Unit] = unitLiteral.asExprOf[Unit]
def builderType: TypeRepr = TypeRepr.of[scala.collection.mutable.Builder]
def OptionType: TypeRepr = TypeRepr.of[Option]
def Some_Apply(tpe: TypeRepr, value: Term): Term =
Select.unique(Ref(SomeModule.companionModule), "apply")
.appliedToType(tpe)
.appliedTo(value)
val commonTypes: List[TypeRepr] =
TypeRepr.of[String] :: TypeRepr.of[Int] :: TypeRepr.of[Long] :: TypeRepr.of[Boolean] :: TypeRepr.of[Double] :: TypeRepr.of[Float] :: ArrayByteType :: ArraySeqByteType :: Nil
val packedTypes: List[TypeRepr] =
TypeRepr.of[Int] :: TypeRepr.of[Long] :: TypeRepr.of[Boolean] :: TypeRepr.of[Double] :: TypeRepr.of[Float] :: Nil
extension (t: TypeRepr)
def isNType: Boolean = t =:= NTpe
def isCaseClass: Boolean = t.typeSymbol.flags.is(Flags.Case)
def isCaseObject: Boolean = t.termSymbol.flags.is(Flags.Case)
def isCaseType: Boolean = t.isCaseClass || t.isCaseObject
def isSealedTrait: Boolean = t.typeSymbol.flags.is(Flags.Sealed) && t.typeSymbol.flags.is(Flags.Trait)
def isIterable: Boolean = t <:< ItetableType && !t.isArraySeqByte
def isArray: Boolean = t <:< ArrayType && !t.isArrayByte
def isRepeated: Boolean = t.isIterable || t.isArray
def isString: Boolean = t =:= TypeRepr.of[String]
def isInt: Boolean = t =:= TypeRepr.of[Int]
def isLong: Boolean = t =:= TypeRepr.of[Long]
def isBoolean: Boolean = t =:= TypeRepr.of[Boolean]
def isDouble: Boolean = t =:= TypeRepr.of[Double]
def isFloat: Boolean = t =:= TypeRepr.of[Float]
def isArrayByte: Boolean = t =:= ArrayByteType
def isArraySeqByte: Boolean = t =:= ArraySeqByteType
def isCommonType: Boolean = commonTypes.exists(_ =:= t)
def isPackedType: Boolean = packedTypes.exists(_ =:= t)
def typeArgsToReplace: Map[String, TypeRepr] =
t.typeSymbol.primaryConstructor.paramSymss
.find(_.headOption.fold(false)( _.isType))
.map(_.map(_.name).zip(t.typeArgs)).getOrElse(Nil)
.toMap
def replaceTypeArgs(map: Map[String, TypeRepr]): TypeRepr = t.asMatchable match
case AppliedType(t1, args) => t1.appliedTo(args.map(_.asMatchable.replaceTypeArgs(map)))
case _ => map.getOrElse(t.typeSymbol.name, t)
def isOption: Boolean = t.asMatchable match
case AppliedType(t1, _) if t1.typeSymbol == OptionClass => true
case _ => false
def typeArgs: List[TypeRepr] = t.dealias.asMatchable match
case AppliedType(t1, args) => args
case _ => Nil
def optionArgument: TypeRepr = t.asMatchable match
case AppliedType(t1, args) if t1.typeSymbol == OptionClass => args.head
case _ => errorAndAbort(s"It isn't Option type: ${t.typeSymbol.name}")
def iterableArgument: TypeRepr = t.baseType(ItetableType.typeSymbol).asMatchable match
case AppliedType(_, args) if t.isIterable => args.head
case _ => errorAndAbort(s"It isn't Iterable (argument) type: ${t.typeSymbol.name}")
def arrayArgument: TypeRepr = t.dealias.asMatchable match
case AppliedType(_, args) if t.isArray => args.head
case _ => errorAndAbort(s"It isn't Array (base) type: ${t.typeSymbol.name}")
def repeatedArgument: TypeRepr =
if t.isIterable then t.iterableArgument
else if t.isArray then t.arrayArgument
else errorAndAbort(s"It isn't Iterable or Array type: ${t.typeSymbol.name}")
def repeatedBaseType: TypeRepr = t.dealias.asMatchable match
case AppliedType(t1, _) if t.isRepeated => t1
case _ => errorAndAbort(s"It isn't Iterable or Array type: ${t.typeSymbol.name}")
def restrictedNums: List[Int] =
val aName = RestrictedNType.typeSymbol.name
val tName = t.typeSymbol.fullName
t.typeSymbol.annotations.collect{ case Apply(Select(New(tpt),_), List(Typed(Repeated(args,_),_))) if tpt.tpe =:= RestrictedNType => args } match
case List(Nil) => errorAndAbort(s"empty annotation ${aName} for `${tName}`")
case List(xs) =>
val nums = xs.collect{
case Literal(IntConstant(n)) => n
case x => errorAndAbort(s"wrong annotation ${aName} for `${tName}` $x")
}
if nums.size != nums.distinct.size then errorAndAbort(s"nums not unique in annotation ${aName} for `${tName}`")
nums
case Nil => Nil
case _ => errorAndAbort(s"multiple ${aName} annotations applied for `${tName}`")
def knownFinalSubclasses: List[Symbol] =
@tailrec def loop(q: List[Symbol], acc: List[Symbol]): List[Symbol] = q match
case Nil => acc
case x :: xs if x.tpe.isSealedTrait => loop(x.tpe.typeSymbol.children ++ xs, acc)
case x :: xs => loop(xs, x :: acc)
loop(t.typeSymbol.children, Nil)
def mkIfStatement(branches: List[(Term, Term)], elseBranch: Term): Term =
branches match
case (cond, thenp) :: xs =>
If(cond, thenp, mkIfStatement(xs, elseBranch))
case Nil => elseBranch
def findCodec(t: TypeRepr): Term =
val tpe = TypeRepr.of[MessageCodec].appliedTo(t)
Implicits.search(tpe) match
case x: ImplicitSearchSuccess => x.tree
case x: ImplicitSearchFailure => errorAndAbort(x.explanation)
def findImplicit(tpe: TypeRepr): Term =
Implicits.search(tpe) match
case x: ImplicitSearchSuccess => x.tree
case x: ImplicitSearchFailure => errorAndAbort(x.explanation)
extension (array_term: Term)
private[proto] def wrapArrayOps(array_tpe: TypeRepr): Term =
Select.unique(Ref(PredefModule), "genericArrayOps").appliedToType(array_tpe.arrayArgument).appliedTo(array_term)
end Common