Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a counter #476

Open
joshewilliams opened this issue Sep 26, 2018 · 7 comments
Open

Creating a counter #476

joshewilliams opened this issue Sep 26, 2018 · 7 comments

Comments

@joshewilliams
Copy link

joshewilliams commented Sep 26, 2018

I was wondering if there was a good way to create a counter. I'm not sure of a good way to describe this, so I'll just go with the example I'm trying to work on. I'm attempting to create a file format parser for the U3D File Format.

Specifically, I'm attempting to handle the Stay or Move field described in 9.6.1.3.4.7 (page 72) which is in the resolution_update type. The Stay or Move field is repeated based on the number of times that the face_orientation in new_face_position_info is 0x01.

Following is my template in its current state, omitting all but the relevant parts:

  resolution_update:
    seq:
      - id: split_position_index
        type: u4
      - id: new_diffuse_color_info
        type: new_diffuse_color_info
      - id: new_specular_color_info
        type: new_specular_color_info
      - id: new_texture_coord_info
        type: new_texture_coord_info
      - id: new_face_count
        type: u4
      - id: new_face_position_info
        type: new_face_position_info
        repeat: expr
        repeat-expr: new_face_count
      - id: stay_or_move
        type: u1
  new_face_position_info:
    seq:
      - id: shading_id
        type: u4
      - id: face_orientation
        type: u1
        enum: face_orientation
      - id: third_position_type
        type: u1
        enum: third_position_type
      - id: local_third_position_index
        type: u4
        if: third_position_type == third_position_type::local_third_position_index
      - id: global_third_position_index
        type: u4
        if: third_position_type == third_position_type::global_third_position_index

I can't think of a good way to do this. If there isn't one, can some sort of counter to Kaitai Struct?

@GreyCat
Copy link
Member

GreyCat commented Sep 26, 2018

Unfortunately, right now there's no good answer to this class of problems in KS.

"Counter", by definition, is imperative, i.e. it relies on a certain way to process (in this case, sequentially parse) the stream.

KS strives to be declarative, i.e. not rely on a particular implementation, but rather describe the essence of the data itself and relationships between data elements. Granted, current implementations that ksc generates is more or less sequential and eager, but it does not mean that other possible implementations would not be so straightforward. For example, we can't rely on the process being parsing (i.e. reading), as opposed to serialization (i.e. writing), and we can't rely on it being sequential and eager (i.e. not lazy).

Probably the best way to solve this class of problems in KS would be to introduce some collection operations that one can invoke in expression language. Given that you state that:

The Stay or Move field is repeated based on the number of times that the face_orientation in new_face_position_info is 0x01.

... we could do it like that:

      - id: stay_or_move
        type: u1
        repeat: expr
        repeat-expr: 'new_face_position_info.count { |x| x.face_orientation == 0x01 }'

where collection.count() being a method which takes one lambda expression / anonymous function (that accepts one collection element and is expected to return boolean), runs it for every element of the collection (passing that element inside) and then counts the number of times it returned true.

Unfortunately, this is not implemented now :(

@joshewilliams
Copy link
Author

Thanks for the quick response! Looks like I might be out of luck with this particular format for now, or I can just ignore the rest of that data stream for the moment. Fortunately, that isn't the only file format I need to work with, so I'll just move on to the others for now.

@GreyCat
Copy link
Member

GreyCat commented Sep 27, 2018

Well, if all else fails, you can always implement that particular type imperatively in your language of choice, i.e. see opaque types.

@Maxzor
Copy link

Maxzor commented Sep 17, 2020

Any update?

@Maxzor
Copy link

Maxzor commented Sep 17, 2020

Thanks to @generalmimon on gitter.im & kaitai-io/kaitai_struct_formats#265 (comment) ,
here is a wip ksy file for git packfile index (.git/objects/pack/*idx) that counts :
kaitai-io/kaitai_struct_formats#323

@KOLANICH
Copy link

here is a ksy file for git packfile index

Could you create a PR into KSF?

@Maxzor
Copy link

Maxzor commented Sep 18, 2020

Will once packfile is done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants