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

io.kaitai.struct.format.InstanceSpec.scala Maven / Gradle / Ivy

package io.kaitai.struct.format

import io.kaitai.struct.datatype.DataType
import io.kaitai.struct.exprlang.{Ast, Expressions}
import io.kaitai.struct.precompile.TypeUndecidedError

sealed abstract class InstanceSpec(val doc: DocSpec) extends MemberSpec {
  def dataTypeComposite: DataType
  def isNullable: Boolean
}
case class ValueInstanceSpec(
  id: InstanceIdentifier,
  path: List[String],
  private val _doc: DocSpec,
  value: Ast.expr,
  ifExpr: Option[Ast.expr],
  var dataTypeOpt: Option[DataType]
) extends InstanceSpec(_doc) {
  override def dataType: DataType = {
    dataTypeOpt match {
      case Some(t) => t
      case None => throw new TypeUndecidedError(id.name)
    }
  }
  override def dataTypeComposite = dataType
  override def isNullable: Boolean = ifExpr.isDefined
  override def isNullableSwitchRaw: Boolean = isNullable
}
case class ParseInstanceSpec(
  id: InstanceIdentifier,
  path: List[String],
  private val _doc: DocSpec,
  dataType: DataType,
  cond: ConditionalSpec,
  pos: Option[Ast.expr],
  io: Option[Ast.expr],
  valid: Option[ValidationSpec]
) extends InstanceSpec(_doc) with AttrLikeSpec {
  override def isLazy = true
}

object InstanceSpec {
  val LEGAL_KEYS_VALUE_INST = Set(
    "value",
    "doc",
    "doc-ref",
    "enum",
    "if"
  )

  def fromYaml(src: Any, path: List[String], metaDef: MetaSpec, id: InstanceIdentifier): InstanceSpec = {
    val srcMap = ParseUtils.asMapStr(src, path)

    ParseUtils.getOptValueExpression(srcMap, "value", path) match {
      case Some(value) =>
        // value instance
        ParseUtils.ensureLegalKeys(srcMap, LEGAL_KEYS_VALUE_INST, path, Some("value instance"))

        // Wrap everything in EnumById if "enum" is used
        val value2 = ParseUtils.getOptValueStr(srcMap, "enum", path) match {
          case None =>
            value
          case Some(enumName) =>
            Ast.expr.EnumById(Ast.identifier(enumName), value)
        }

        val ifExpr = ParseUtils.getOptValueExpression(srcMap, "if", path)

        ValueInstanceSpec(
          id,
          path,
          DocSpec.fromYaml(srcMap, path),
          value2,
          ifExpr,
          None
        )
      case None =>
        // normal parse instance
        // TODO: perform proper validation of parse instance keys
        // ParseUtils.ensureLegalKeys(srcMap, LEGAL_KEYS_PARSE_INST, path, Some("parse instance"))

        val pos = ParseUtils.getOptValueExpression(srcMap, "pos", path)
        val io = ParseUtils.getOptValueExpression(srcMap, "io", path)

        val fakeAttrMap = srcMap.filterKeys((key) => key != "pos" && key != "io")
        val a = AttrSpec.fromYaml(fakeAttrMap, path, metaDef, id)
        val valid = srcMap.get("valid").map(ValidationSpec.fromYaml(_, path ++ List("valid")))

        ParseInstanceSpec(id, path, a.doc, a.dataType, a.cond, pos, io, valid)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy