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

io.kaitai.struct.languages.components.CommonReads.scala Maven / Gradle / Ivy

package io.kaitai.struct.languages.components

import io.kaitai.struct.datatype._
import io.kaitai.struct.datatype.DataType.{SwitchType, UserTypeFromBytes, BytesType}
import io.kaitai.struct.exprlang.Ast
import io.kaitai.struct.format._

trait CommonReads extends LanguageCompiler {
  override def attrParse(attr: AttrLikeSpec, id: Identifier, defEndian: Option[Endianness]): Unit = {
    attrParseIfHeader(id, attr.cond.ifExpr)

    // Manage IO & seeking for ParseInstances
    val io = attr match {
      case pis: ParseInstanceSpec =>
        val io = pis.io match {
          case None => normalIO
          case Some(ex) => useIO(ex)
        }
        pis.pos.foreach { pos =>
          pushPos(io)
          seek(io, pos)
        }
        io
      case _ =>
        // no seeking required for sequence attributes
        normalIO
    }

    if (config.readStoresPos)
      attrDebugStart(id, attr.dataType, Some(io), NoRepeat)

    defEndian match {
      case Some(_: CalcEndian) | Some(InheritedEndian) =>
        attrParseHybrid(
          () => attrParse0(id, attr, io, Some(LittleEndian)),
          () => attrParse0(id, attr, io, Some(BigEndian))
        )
      case None =>
        attrParse0(id, attr, io, None)
      case Some(fe: FixedEndian) =>
        attrParse0(id, attr, io, Some(fe))
    }

    if (config.readStoresPos)
      attrDebugEnd(id, attr.dataType, io, NoRepeat)

    // More position management + set calculated flag after parsing for ParseInstanceSpecs
    attr match {
      case pis: ParseInstanceSpec =>
        // Restore position, if applicable
        if (pis.pos.isDefined)
          popPos(io)

        // Mark parse instance as calculated
        instanceSetCalculated(pis.id)
      case _ => // no seeking required for sequence attributes
    }

    // Run validations (still inside "if", if applicable)
    attrValidateAll(attr)

    attrParseIfFooter(attr.cond.ifExpr)
  }

  def attrParse0(id: Identifier, attr: AttrLikeSpec, io: String, defEndian: Option[FixedEndian]): Unit = {
    if (attr.cond.repeat != NoRepeat)
      condRepeatCommonInit(id, attr.dataType, needRaw(attr.dataType))
    attr.cond.repeat match {
      case RepeatEos =>
        condRepeatEosHeader(id, io, attr.dataType)
      case RepeatExpr(repeatExpr: Ast.expr) =>
        condRepeatExprHeader(id, io, attr.dataType, repeatExpr)
      case RepeatUntil(untilExpr: Ast.expr) =>
        condRepeatUntilHeader(id, io, attr.dataType, untilExpr)
      case NoRepeat =>
    }
    attrParse2(id, attr.dataType, io, attr.cond.repeat, false, defEndian)
    attr.cond.repeat match {
      case RepeatEos =>
        condRepeatEosFooter
      case _: RepeatExpr =>
        condRepeatExprFooter
      case RepeatUntil(untilExpr: Ast.expr) =>
        condRepeatUntilFooter(id, io, attr.dataType, untilExpr)
      case NoRepeat =>
    }
  }

  def attrParse2(id: Identifier, dataType: DataType, io: String, rep: RepeatSpec, isRaw: Boolean, defEndian: Option[FixedEndian], assignType: Option[DataType] = None): Unit

  def needRaw(dataType: DataType): NeedRaw = {
    val rawIo = dataType match {
      case _: UserTypeFromBytes => true
      case st: SwitchType => st.hasSize
      case _ => false
    }
    val rawProcess = dataType match {
      case bt: BytesType => bt.process.nonEmpty
      case utfb: UserTypeFromBytes => utfb.bytes.process.nonEmpty
      case _ => false
    }
    (rawIo, rawProcess) match {
      case (true, false) => RawIo
      case (false, true) => RawProcess
      case (true, true) => RawIoProcess
      case _ => NotRaw
    }
  }

  def attrDebugStart(attrName: Identifier, attrType: DataType, io: Option[String], repeat: RepeatSpec): Unit = {}
  def attrDebugEnd(attrName: Identifier, attrType: DataType, io: String, repeat: RepeatSpec): Unit = {}

  /**
    * Runs all validation procedures requested for an attribute.
    * @param attr attribute to run validations for
    */
  def attrValidateAll(attr: AttrLikeSpec) =
    attr.valid.foreach(valid => attrValidate(attr.id, attr, valid))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy