Decode modules abstractely in scenario-service server (#1844)

* add scenario Module decoding to Decode.OfPackage

* use purely data-driven decoding in scenario service in Scala

- decouples scenario service from LF decoder implementation

* make DecodeV1 companion private

* make extension to LFv2 more obvious
This commit is contained in:
Stephen Compall 2019-06-25 09:49:04 +02:00 committed by GitHub
parent 9de01124e6
commit 5b480c99ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 18 deletions

View File

@ -3,8 +3,7 @@
package com.digitalasset.daml.lf.scenario
import com.digitalasset.daml_lf.DamlLf1
import com.digitalasset.daml.lf.archive.{Decode, DecodeV1}
import com.digitalasset.daml.lf.archive.Decode
import com.digitalasset.daml.lf.archive.Decode.ParseError
import com.digitalasset.daml.lf.data.Ref.{Identifier, ModuleName, PackageId, QualifiedName}
import com.digitalasset.daml.lf.language.{Ast, LanguageVersion}
@ -70,6 +69,21 @@ class Context(val contextId: Context.ContextId) {
newCtx
}
private def decodeModule(
major: LanguageVersion.Major,
minor: String,
bytes: ByteString): Ast.Module = {
val lfVer = LanguageVersion(major, LanguageVersion.Minor fromProtoIdentifier minor)
val dop: Decode.OfPackage[_] = Decode.decoders
.lift(lfVer)
.getOrElse(throw Context.ContextException(s"No decode support for LF ${lfVer.pretty}"))
.decoder
val lfMod = dop.protoModule(
Decode.damlLfCodedInputStream(bytes.newInput)
)
dop.decodeScenarioModule(homePackageId, lfMod)
}
private def validate(pkgIds: Traversable[PackageId], forScenarioService: Boolean): Unit = {
val validator: PackageId => Either[ValidationError, Unit] =
if (forScenarioService)
@ -112,17 +126,7 @@ class Context(val contextId: Context.ContextId) {
val lfModules = loadModules.map(module =>
module.getModuleCase match {
case ProtoModule.ModuleCase.DAML_LF_1 =>
// TODO this duplicates/skips the similar logic and extra version
// support check from `Decode`'s functions; will improperly accept
// too-new versions as a result
val lfMod = DamlLf1.Module
.parser()
.parseFrom(
Decode.damlLfCodedInputStream(module.getDamlLf1.newInput)
)
new DecodeV1(LanguageVersion.Minor fromProtoIdentifier module.getMinor)
.ModuleDecoder(homePackageId, lfMod)
.decode()
decodeModule(LanguageVersion.Major.V1, module.getMinor, module.getDamlLf1)
case ProtoModule.ModuleCase.DAML_LF_DEV | ProtoModule.ModuleCase.MODULE_NOT_SET =>
throw Context.ContextException("Module.MODULE_NOT_SET")
})

View File

@ -46,7 +46,7 @@ object Decode extends Decode {
Reader.damlLfCodedInputStream(is, recursionLimit)
/** inlined [[scalaz.ContravariantCoyoneda]]`[OfPackage, DamlLf.ArchivePayload]` */
private[archive] sealed abstract class PayloadDecoder {
private[lf] sealed abstract class PayloadDecoder {
type I
val extract: DamlLf.ArchivePayload => I
val decoder: OfPackage[I]
@ -61,13 +61,18 @@ object Decode extends Decode {
}
}
override private[archive] val decoders: PartialFunction[LanguageVersion, PayloadDecoder] = {
override private[lf] val decoders: PartialFunction[LanguageVersion, PayloadDecoder] = {
case LanguageVersion(V1, minor) if V1.supportedMinorVersions.contains(minor) =>
PayloadDecoder(new DecodeV1(minor))(_.getDamlLf1)
}
private[lf] trait OfPackage[-Pkg] {
type ProtoModule
def protoModule(cis: CodedInputStream): ProtoModule
@throws[ParseError]
def decodePackage(packageId: PackageId, lfPackage: Pkg): Package
@throws[ParseError]
def decodeScenarioModule(packageId: PackageId, lfModule: ProtoModule): Module
}
private def identifierStart(c: Char) =

View File

@ -13,10 +13,12 @@ import com.digitalasset.daml.lf.language.Util._
import com.digitalasset.daml.lf.language.{Ast, LanguageMinorVersion, LanguageVersion}
import com.digitalasset.daml_lf.{DamlLf1 => PLF}
import com.google.protobuf.CodedInputStream
import scala.collection.JavaConverters._
import scala.collection.mutable
private[lf] class DecodeV1(minor: LanguageMinorVersion) extends Decode.OfPackage[PLF.Package] {
private[archive] class DecodeV1(minor: LanguageMinorVersion) extends Decode.OfPackage[PLF.Package] {
import Decode._
@ -27,6 +29,14 @@ private[lf] class DecodeV1(minor: LanguageMinorVersion) extends Decode.OfPackage
override def decodePackage(packageId: PackageId, lfPackage: PLF.Package): Package =
Package(lfPackage.getModulesList.asScala.map(ModuleDecoder(packageId, _).decode))
type ProtoModule = PLF.Module
override def protoModule(cis: CodedInputStream): ProtoModule =
PLF.Module.parser().parseFrom(cis)
override def decodeScenarioModule(packageId: PackageId, lfModule: ProtoModule): Module =
ModuleDecoder(packageId, lfModule).decode()
private[this] def eitherToParseError[A](x: Either[String, A]): A =
x.fold(err => throw new ParseError(err), identity)
@ -670,7 +680,7 @@ private[lf] class DecodeV1(minor: LanguageMinorVersion) extends Decode.OfPackage
}
object DecodeV1 {
private[lf] object DecodeV1 {
import LanguageMinorVersion.Implicits._
private[lf] val primTypeTable: Map[PLF.PrimType, (BuiltinType, LanguageMinorVersion)] = {

View File

@ -5,7 +5,9 @@ package com.digitalasset.daml.lf.language
import com.digitalasset.daml.lf.language.{LanguageMajorVersion => LMV}
final case class LanguageVersion(major: LanguageMajorVersion, minor: LanguageMinorVersion)
final case class LanguageVersion(major: LanguageMajorVersion, minor: LanguageMinorVersion) {
def pretty: String = s"${major.pretty}.${minor.toProtoIdentifier}"
}
object LanguageVersion {