diff --git a/shared/src/main/scala/io/kaitai/struct/datatype/DataType.scala b/shared/src/main/scala/io/kaitai/struct/datatype/DataType.scala index 96e6f4036..85a86765d 100644 --- a/shared/src/main/scala/io/kaitai/struct/datatype/DataType.scala +++ b/shared/src/main/scala/io/kaitai/struct/datatype/DataType.scala @@ -244,11 +244,14 @@ object DataType { case class CalcKaitaiStructType(override val isOwningInExpr: Boolean = false) extends StructType { def isOwning = false } - case object OwnedKaitaiStreamType extends ComplexDataType { + + /** Base class for streams from which types can be read or written. */ + abstract sealed class StreamType extends ComplexDataType + case object OwnedKaitaiStreamType extends StreamType { def isOwning = true override def asNonOwning(isOwningInExpr: Boolean = false): DataType = KaitaiStreamType } - case object KaitaiStreamType extends ComplexDataType { + case object KaitaiStreamType extends StreamType { def isOwning = false } diff --git a/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala index 97693c473..51ac0ed2b 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/CSharpCompiler.scala @@ -685,7 +685,7 @@ object CSharpCompiler extends LanguageCompilerStatic case AnyType => "object" case KaitaiStructType | CalcKaitaiStructType(_) => kstructName - case KaitaiStreamType | OwnedKaitaiStreamType => kstreamName + case _: StreamType => kstreamName case t: UserType => types2class(t.name) case EnumType(name, _) => types2class(name) diff --git a/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala index 49e4343e1..8b5ea9678 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/GoCompiler.scala @@ -667,7 +667,7 @@ object GoCompiler extends LanguageCompilerStatic case AnyType => "interface{}" case KaitaiStructType | CalcKaitaiStructType(_) => kstructName - case KaitaiStreamType | OwnedKaitaiStreamType => s"*$kstreamName" + case _: StreamType => s"*$kstreamName" case t: UserType => "*" + types2class(t.classSpec match { case Some(cs) => cs.name diff --git a/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala index ee19058d3..0b460e794 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/JavaCompiler.scala @@ -870,7 +870,7 @@ object JavaCompiler extends LanguageCompilerStatic case _: BytesType => "byte[]" case AnyType => "Object" - case KaitaiStreamType | OwnedKaitaiStreamType => kstreamName + case _: StreamType => kstreamName case KaitaiStructType | CalcKaitaiStructType(_) => kstructName case t: UserType => types2class(t.name) @@ -914,7 +914,7 @@ object JavaCompiler extends LanguageCompilerStatic case _: BytesType => "byte[]" case AnyType => "Object" - case KaitaiStreamType | OwnedKaitaiStreamType => kstreamName + case _: StreamType => kstreamName case KaitaiStructType | CalcKaitaiStructType(_) => kstructName case t: UserType => types2class(t.name) diff --git a/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala index 21868c146..c2f857cac 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/NimCompiler.scala @@ -582,7 +582,7 @@ object NimCompiler extends LanguageCompilerStatic case _: BytesType => "seq[byte]" case KaitaiStructType | CalcKaitaiStructType(_) => "KaitaiStruct" - case KaitaiStreamType | OwnedKaitaiStreamType => "KaitaiStream" + case _: StreamType => "KaitaiStream" case t: UserType => namespaced(t.classSpec match { case Some(cs) => cs.name diff --git a/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala b/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala index c2c4d1476..24005340f 100644 --- a/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala +++ b/shared/src/main/scala/io/kaitai/struct/languages/PHPCompiler.scala @@ -497,7 +497,7 @@ class PHPCompiler(typeProvider: ClassTypeProvider, config: RuntimeConfig) case _: ArrayType => "array" case KaitaiStructType | CalcKaitaiStructType(_) => kstructName - case KaitaiStreamType | OwnedKaitaiStreamType => kstreamName + case _: StreamType => kstreamName } } 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 6b177d35e..1f751d4b9 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/CommonMethods.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/CommonMethods.scala @@ -26,6 +26,9 @@ object MethodArgType { case object ArrayArg extends MethodArgType { override def toString = "array" } + case object StreamArg extends MethodArgType { + override def toString = "io stream" + } def byDataType(dataType: DataType): Option[MethodArgType] = { dataType match { @@ -35,6 +38,7 @@ object MethodArgType { case _: BooleanType => Some(BooleanArg) case _: BytesType => Some(BytesArg) case _: ArrayType => Some(ArrayArg) + case _: StreamType => Some(StreamArg) case _ => None } } @@ -133,6 +137,12 @@ abstract trait CommonMethods[T] extends TypeDetector { MethodSig0("min", AnyType, arrayMin), MethodSig0("max", AnyType, arrayMax), ), + + StreamArg -> List( + MethodSig0("eof", CalcBooleanType, kaitaiStreamEof), + MethodSig0("pos", CalcIntType, kaitaiStreamPos), + MethodSig0("size", CalcIntType, kaitaiStreamSize), + ), ) /** @@ -170,12 +180,6 @@ abstract trait CommonMethods[T] extends TypeDetector { } case ut: UserType => userTypeField(ut, value, attr.name) - case KaitaiStreamType | OwnedKaitaiStreamType => - attr.name match { - case "size" => kaitaiStreamSize(value) - case "eof" => kaitaiStreamEof(value) - case "pos" => kaitaiStreamPos(value) - } case et: EnumType => attr.name match { case "to_i" => enumToInt(value, et) 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 49cf61ef2..b96716896 100644 --- a/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala +++ b/shared/src/main/scala/io/kaitai/struct/translators/TypeDetector.scala @@ -4,7 +4,7 @@ import io.kaitai.struct.datatype.DataType import io.kaitai.struct.datatype.DataType._ import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format.Identifier -import io.kaitai.struct.precompile.{MethodNotFoundError, TypeMismatchError, TypeUndecidedError} +import io.kaitai.struct.precompile.{MethodNotFoundError, MethodNotFoundErrorWithArg, TypeMismatchError, TypeUndecidedError} /** * Basic class the implements type inferring functionality for Ast.expr @@ -172,24 +172,28 @@ class TypeDetector(provider: TypeProvider) { attr.name match { case "length" | "size" => CalcIntType case "first" | "last" | "min" | "max" => Int1Type(false) - case _ => throw new MethodNotFoundError(attr.name, valType) + // MethodArgType.byDataType returns Some(...) in that case + case _ => throw new MethodNotFoundErrorWithArg(attr.name, MethodArgType.byDataType(valType).get) } case _: StrType => attr.name match { case "length" => CalcIntType case "reverse" => CalcStrType case "to_i" => CalcIntType - case _ => throw new MethodNotFoundError(attr.name, valType) + // MethodArgType.byDataType returns Some(...) in that case + case _ => throw new MethodNotFoundErrorWithArg(attr.name, MethodArgType.byDataType(valType).get) } case _: IntType => attr.name match { case "to_s" => CalcStrType - case _ => throw new MethodNotFoundError(attr.name, valType) + // MethodArgType.byDataType returns Some(...) in that case + case _ => throw new MethodNotFoundErrorWithArg(attr.name, MethodArgType.byDataType(valType).get) } case _: FloatType => attr.name match { case "to_i" => CalcIntType - case _ => throw new MethodNotFoundError(attr.name, valType) + // MethodArgType.byDataType returns Some(...) in that case + case _ => throw new MethodNotFoundErrorWithArg(attr.name, MethodArgType.byDataType(valType).get) } case ArrayTypeInStream(_) | CalcArrayType(_, _) => val inType = valType match { @@ -211,14 +215,16 @@ class TypeDetector(provider: TypeProvider) { attr.name match { case "first" | "last" | "min" | "max" => inType case "size" => CalcIntType - case _ => throw new MethodNotFoundError(attr.name, valType) + // MethodArgType.byDataType returns Some(...) in that case + case _ => throw new MethodNotFoundErrorWithArg(attr.name, MethodArgType.byDataType(valType).get) } - case KaitaiStreamType | OwnedKaitaiStreamType => + case _: StreamType => attr.name match { case "size" => CalcIntType case "pos" => CalcIntType case "eof" => CalcBooleanType - case _ => throw new MethodNotFoundError(attr.name, valType) + // MethodArgType.byDataType returns Some(...) in that case + case _ => throw new MethodNotFoundErrorWithArg(attr.name, MethodArgType.byDataType(valType).get) } case et: EnumType => attr.name match { @@ -228,7 +234,8 @@ class TypeDetector(provider: TypeProvider) { case _: BooleanType => attr.name match { case "to_i" => CalcIntType - case _ => throw new MethodNotFoundError(attr.name, valType) + // MethodArgType.byDataType returns Some(...) in that case + case _ => throw new MethodNotFoundErrorWithArg(attr.name, MethodArgType.byDataType(valType).get) } case _ => throw new MethodNotFoundError(attr.name, valType) @@ -253,7 +260,10 @@ class TypeDetector(provider: TypeProvider) { case (_: StrType, "to_i") => CalcIntType case (_: BytesType, "to_s") => CalcStrType case _ => - throw new MethodNotFoundError(methodName.name, objType) + MethodArgType.byDataType(objType) match { + case Some(argType) => throw new MethodNotFoundErrorWithArg(methodName.name, argType) + case None => throw new MethodNotFoundError(methodName.name, objType) + } } } }