diff --git a/shared/src/main/scala/io/kaitai/struct/translators/CommonMethods.scala b/shared/src/main/scala/io/kaitai/struct/translators/CommonMethods.scala index 93786825f..ca7c438d3 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CommonMethods.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CommonMethods.scala @@ -181,6 +181,7 @@ abstract trait CommonMethods[T] extends TypeDetector { case et: EnumType => attr.name match { case "to_i" => enumToInt(value, et) + case "to_s" => enumToStr(value, et) case _ => throw new TypeMismatchError(s"called invalid attribute '${attr.name}' on expression of type $valType") } case _ => @@ -278,6 +279,7 @@ abstract trait CommonMethods[T] extends TypeDetector { def arrayMax(a: Ast.expr): T def enumToInt(value: Ast.expr, et: EnumType): T + def enumToStr(value: Ast.expr, et: EnumType): T = ??? def boolToInt(value: Ast.expr): T diff --git a/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala b/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala index 8d2741282..7f678fed8 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/ExpressionValidator.scala @@ -136,6 +136,7 @@ class ExpressionValidator(val provider: TypeProvider) override def arrayMax(a: Ast.expr): Unit = validate(a) override def enumToInt(value: Ast.expr, et: DataType.EnumType): Unit = validate(value) + override def enumToStr(value: Ast.expr, et: DataType.EnumType): Unit = validate(value) override def boolToInt(value: Ast.expr): Unit = validate(value) diff --git a/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala index 3bc4fe391..5822f33b1 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/JavaScriptTranslator.scala @@ -84,6 +84,12 @@ class JavaScriptTranslator(provider: TypeProvider, importList: ImportList) exten override def enumToInt(v: expr, et: EnumType): String = translate(v) + override def enumToStr(v: expr, et: EnumType): String = { + val enumSpec = et.enumSpec.get + val isExternal = enumSpec.isExternal(provider.nowClass) + val enumObjName = JavaScriptCompiler.types2class(enumSpec.name, isExternal) + s"$enumObjName[${translate(v)}].toLowerCase()" + } /** * Converts a boolean (true or false) to integer (1 or 0, respectively) in diff --git a/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala index 54c1e7da9..24a26fa7b 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/JavaTranslator.scala @@ -1,12 +1,12 @@ package io.kaitai.struct.translators -import io.kaitai.struct.{ClassTypeProvider, ImportList, RuntimeConfig, Utils} -import io.kaitai.struct.exprlang.Ast -import io.kaitai.struct.exprlang.Ast._ import io.kaitai.struct.datatype.DataType import io.kaitai.struct.datatype.DataType._ +import io.kaitai.struct.exprlang.Ast +import io.kaitai.struct.exprlang.Ast._ import io.kaitai.struct.format.{EnumSpec, Identifier} import io.kaitai.struct.languages.JavaCompiler +import io.kaitai.struct.{ImportList, RuntimeConfig, Utils} class JavaTranslator(provider: TypeProvider, importList: ImportList, config: RuntimeConfig) extends BaseTranslator(provider) { override def doIntLiteral(n: BigInt): String = { @@ -114,8 +114,14 @@ class JavaTranslator(provider: TypeProvider, importList: ImportList, config: Run // Predefined methods of various types override def strToInt(s: expr, base: expr): String = s"Long.parseLong(${translate(s)}, ${translate(base)})" + override def enumToInt(v: expr, et: EnumType): String = s"${translate(v)}.id()" + override def enumToStr(v: Ast.expr, et: EnumType): String = { + importList.add("java.util.Locale"); + s"${translate(v, METHOD_PRECEDENCE)}.toString().toLowerCase(Locale.ROOT)" + } + override def floatToInt(v: expr): String = doCast(v, CalcIntType) override def intToStr(i: expr): String = diff --git a/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala index 69dafd292..bc1d17f03 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/PythonTranslator.scala @@ -140,8 +140,12 @@ class PythonTranslator(provider: TypeProvider, importList: ImportList, config: R } s"int(${translate(s)}$add)" } + override def enumToInt(v: Ast.expr, et: EnumType): String = s"int(${translate(v)})" + override def enumToStr(v: Ast.expr, et: EnumType): String = + s"${translate(v)}.name" + override def boolToInt(v: Ast.expr): String = s"int(${translate(v)})" override def floatToInt(v: Ast.expr): String = diff --git a/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala b/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala index c161dda75..d838fc3e0 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/RubyTranslator.scala @@ -126,6 +126,15 @@ class RubyTranslator(provider: TypeProvider) extends BaseTranslator(provider) val value = translate(v) s"(${enumInverseMap(et)}[$value] || $value)" } + override def enumToStr(v: Ast.expr, et: EnumType): String = { + // Ruby enums are implemented as symbols which have bare enum name + `_` + label. + // Here we just need the label part, so we'll strip the enum name prefix. + + val enumPrefixLength = et.name.last.length + 1 // +1 for the underscore + + s"${translate(v, METHOD_PRECEDENCE)}.to_s[$enumPrefixLength..-1]" + } + override def floatToInt(v: Ast.expr): String = s"${translate(v, METHOD_PRECEDENCE)}.to_i" override def intToStr(i: Ast.expr): String = diff --git a/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala b/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala index 04882f6bd..40a726d8d 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala @@ -223,6 +223,7 @@ class TypeDetector(provider: TypeProvider) { case et: EnumType => attr.name match { case "to_i" => CalcIntType + case "to_s" => CalcStrType case _ => throw new MethodNotFoundError(attr.name, valType) } case _: BooleanType =>