kaitai_struct icon indicating copy to clipboard operation
kaitai_struct copied to clipboard

[Java] java.lang.Long cannot be converted to int

Open SkypLabs opened this issue 2 years ago • 6 comments

Hi,

I'm having an issue when trying to use this Java class: https://formats.kaitai.io/ds_store/java.html

Line 662 returns the following error: incompatible types: java.lang.Long cannot be converted to int

Here is my setup:

  • kaitai-struct-compiler: 0.9
  • JDK: openjdk version "17.0.2" 2022-01-18

Let me know if you need any more information.

SkypLabs avatar Mar 27 '22 22:03 SkypLabs

I’ve also experienced this issue with Java 11. (Seems likely to impact any java version.)

kingthorin avatar Mar 27 '22 23:03 kingthorin

Another reminder that we need to dig much deeper into boxed numeric types in Java.

generalmimon avatar May 25 '22 20:05 generalmimon

Anyone know if the ds_store struct has been regenerated following the above mentioned fix? ☝️

kingthorin avatar Oct 15 '22 02:10 kingthorin

@kingthorin:

Anyone know if the ds_store struct has been regenerated following the above mentioned fix? ☝️

It hasn't - all parsers in the format gallery are always built using the latest stable compiler, which is 0.10 at this point. The above fix https://github.com/kaitai-io/kaitai_struct_compiler/commit/604359d63b7d98511828913e206a85f105d3993a is only on the serialization branch so far, so it must be first merged to master and then it can appear in a new version (but that isn't likely to happen anytime soon).

But this issue (and pretty much all "type X cannot be converted to Y" problems in user expressions) can in fact be worked around with type casting, if you are blocked by it - in this case, the problem is that

  1. block_id is a u4 integer (Java's int is signed, so it cannot hold the entire range of u4 and long is used instead) AND
  2. block_id is conditional (has if - that changes its type to boxed instead of the primitive type), so Long is used instead of primitive long.

Java only supports int array indices, so the compiler has the (int) casting of "whatever the subscript expression is" hardcoded (JavaTranslator.scala:102-103):

  override def arraySubscript(container: expr, idx: expr): String =
    s"${translate(container)}.get((int) ${translate(idx)})"

And the Long cannot be converted to int using (int) ... directly, as we've seen.

However, if you manually cast block_id to primitive long by using a type cast .as<u4>, it will be translated into .get((int) ((long) ...)), which will already work. See macos/ds_store.ksy:156-172:

     types:
       block_data:
         params:
           - id: mode
             type: u4
         seq:
           - id: block_id
             type: u4
             if: mode > 0
           - id: record
             type: record
         instances:
           block:
             io: _root._io
-            pos: _root.buddy_allocator_body.block_addresses[block_id].offset
+            pos: _root.buddy_allocator_body.block_addresses[block_id.as<u4>].offset
             type: block
             if: mode > 0

As anticipated:

@@ -659,7 +659,7 @@ public class DsStore extends KaitaiStruct {
                 if (mode() > 0) {
                     KaitaiStream io = _root()._io();
                     long _pos = io.pos();
-                    io.seek(_root().buddyAllocatorBody().blockAddresses().get((int) blockId()).offset());
+                    io.seek(_root().buddyAllocatorBody().blockAddresses().get((int) ((long) (blockId()))).offset());
                     this.block = new Block(io, this, _root);
                     io.seek(_pos);
                 }

I guess it makes sense to add this workaround to the official ds_store.ksy. Even when the compiler will be able to handle it in Java, I assume that C# will have exactly the same problem, because I had to add a bunch of typecasts in the coreldraw_cdr.ksy spec I'm working on (https://github.com/kaitai-io/coreldraw_cdr.ksy/search?q=C%23&type=commits) to make it compile in C#.

generalmimon avatar Oct 15 '22 09:10 generalmimon

@generalmimon thank you for the very detailed response, I'll see where I can get with it.

kingthorin avatar Oct 15 '22 20:10 kingthorin

Many thanks @generalmimon for your insights!

I just created a PR to apply your fix to my ds_store.ksy in the format gallery: https://github.com/kaitai-io/kaitai_struct_formats/pull/632

SkypLabs avatar Nov 02 '22 18:11 SkypLabs