
io.kaitai.struct.GoClassCompiler.scala Maven / Gradle / Ivy
package io.kaitai.struct
import io.kaitai.struct.datatype.DataType.{CalcIntType, KaitaiStreamType, UserTypeInstream}
import io.kaitai.struct.datatype.{BigEndian, CalcEndian, Endianness, FixedEndian, InheritedEndian, LittleEndian}
import io.kaitai.struct.exprlang.Ast
import io.kaitai.struct.format._
import io.kaitai.struct.languages.GoCompiler
import io.kaitai.struct.languages.components.ExtraAttrs
class GoClassCompiler(
classSpecs: ClassSpecs,
override val topClass: ClassSpec,
config: RuntimeConfig
) extends ClassCompiler(classSpecs, topClass, config, GoCompiler) {
override def compileClass(curClass: ClassSpec): Unit = {
provider.nowClass = curClass
val extraAttrs = List(
AttrSpec(List(), IoIdentifier, KaitaiStreamType),
AttrSpec(List(), RootIdentifier, UserTypeInstream(topClassName, None)),
AttrSpec(List(), ParentIdentifier, curClass.parentType)
) ++ ExtraAttrs.forClassSpec(curClass, lang)
if (!curClass.doc.isEmpty)
lang.classDoc(curClass.name, curClass.doc)
// Enums declaration defines types, so they need to go first
compileEnums(curClass)
// Basic struct declaration
lang.classHeader(curClass.name)
compileAttrDeclarations(curClass.seq ++ curClass.params ++ extraAttrs)
curClass.instances.foreach { case (instName, instSpec) =>
compileInstanceDeclaration(instName, instSpec)
}
lang.classFooter(curClass.name)
// Constructor = Read() function
compileReadFunction(curClass)
compileInstances(curClass)
compileAttrReaders(curClass.seq ++ extraAttrs)
// Recursive types
compileSubclasses(curClass)
}
def compileReadFunction(curClass: ClassSpec) = {
lang.classConstructorHeader(
curClass.name,
curClass.parentType,
topClassName,
curClass.meta.endian.contains(InheritedEndian),
curClass.params
)
compileEagerRead(curClass.seq, curClass.meta.endian)
lang.classConstructorFooter
}
override def compileInstance(className: List[String], instName: InstanceIdentifier, instSpec: InstanceSpec, endian: Option[Endianness]): Unit = {
// Determine datatype
val dataType = instSpec.dataTypeComposite
if (!instSpec.doc.isEmpty)
lang.attributeDoc(instName, instSpec.doc)
lang.instanceHeader(className, instName, dataType, instSpec.isNullable)
lang.instanceCheckCacheAndReturn(instName, dataType)
instSpec match {
case vi: ValueInstanceSpec =>
lang.attrParseIfHeader(instName, vi.ifExpr)
lang.instanceCalculate(instName, dataType, vi.value)
lang.attrParseIfFooter(vi.ifExpr)
case i: ParseInstanceSpec =>
lang.attrParse(i, instName, endian)
}
lang.instanceSetCalculated(instName)
lang.instanceReturn(instName, dataType)
lang.instanceFooter
}
override def compileCalcEndian(ce: CalcEndian): Unit = {
def renderProc(result: FixedEndian): Unit = {
val v = result match {
case LittleEndian => Ast.expr.IntNum(1)
case BigEndian => Ast.expr.IntNum(0)
}
lang.instanceCalculate(IS_LE_ID, CalcIntType, v)
}
lang.switchCases[FixedEndian](IS_LE_ID, ce.on, ce.cases, renderProc, renderProc)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy