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

How to dynamically switch type based on a condition? #584

Closed
takase1121 opened this issue May 25, 2019 · 20 comments
Closed

How to dynamically switch type based on a condition? #584

takase1121 opened this issue May 25, 2019 · 20 comments
Labels

Comments

@takase1121
Copy link

takase1121 commented May 25, 2019

  - id: ar
    type: '_parent.osu_ver < 20140609 ? u1 : f4'
  - id: cs
    type: '_parent.osu_ver < 20140609 ? u1 : f4'
  - id: hpd
    type: '_parent.osu_ver < 20140609 ? u1 : f4'
  - id: od
    type: '_parent.osu_ver < 20140609 ? u1 : f4'

This will not work as kaitai parses that as the type without checking it. Case does not work (at least in my case) when used to compare values. What else can I do to achieve the same effect?

@KOLANICH
Copy link

KOLANICH commented May 25, 2019

Please NEVER post source code as screenshots 👿👿👿👿.

Case does not work (at least in my case) when used to compare values.

What is your code? Can osu_ver be uniquely addressed from _root?

Also, as you have the same selection of the type in each field, it is obvious you should encapsulate it into a type.

You may also want to subscribe to #88 .

@takase1121
Copy link
Author

What is your code? Can osu_ver be uniquely addressed from _root?

type:
  switch-on: _unplayed
  cases:
    _parent.osu_ver < 20140609: u1
    _: f4

I remembered its something like this. _unplayed is simply another random b1 so I can somehow do the comparison

Also, as you have the same selection of the type in each field, it is obvious you should encapsulate it into a type.

I don't really understand it. I just begin using kaitai last few hours ago

@takase1121
Copy link
Author

oh and also I think i tried using _root but it doesn't work

@dgelessus
Copy link
Contributor

@takase1121 I would suggest writing the condition like this:

type:
  switch-on: _parent.osu_ver < 20140609
  cases:
    true: u1
    false: f4

That way you don't have to use another unrelated field in the condition.

I think @KOLANICH's suggestion is that you should define the u1/f4 switch as a separate type, so that you don't have to copy the switch block every time. Something like this:

seq:
  - id: cs
    type: version_dependent_number
  - id: hpd
    type: version_dependent_number
  - id: od
    type: version_dependent_number
types:
  version_dependent_number:
    seq:
      - id: value
        type:
          switch-on: _parent.osu_ver < 20140609
          cases:
            true: u1
            false: f4

@KOLANICH
Copy link

KOLANICH commented May 25, 2019

As I understand, you are implementing https://osu.ppy.sh/help/wiki/osu!_File_Formats/Db_(file_format)

So

seq:
  - id: osu_ver
    type: u4
 ....
instances:
  float_or_int_selector:
    value: osu_ver < 20140609
types:
  float_or_int:
    seq:
      - id: value
        type:
          switch-on: _root.float_or_int_selector
          cases:
            true: u1
            false: f4

@takase1121
Copy link
Author

Oh my. I must be a mega idiot to not realize I can do that

@takase1121
Copy link
Author

As I understand, younare implementing https://osu.ppy.sh/help/wiki/osu!_File_Formats/Db_(file_format)

Yes

@takase1121
Copy link
Author

@dgelessus I tried your method and this happens when I run the script through ksv

Compilation OK
... processing main.ksy 0
Error: [{"file"=>"main.ksy", "path"=>[], "message"=>"called attribute 'osu_ver' on generic struct expression 'Name(identifier(_parent))'"}]
Fatal errors encountered, cannot continue```

@takase1121
Copy link
Author

@KOLANICH I have the Beatmap object in a seperate file. Where should I put this?

@KOLANICH
Copy link

I don't understand the question. It is a module you can use in an own program.

@takase1121
Copy link
Author

takase1121 commented May 25, 2019

@KOLANICH sorry i wasnt clear
I mean I have a file called Beatmap.ksy where I handle the Beatmap object
image

and another file called main.ksy that handles the whole target file as a whole.
Now which file should I put the code you gave into?
osu_ver is in main.ksy and the logic I posted is in Beatmap.ksy

@KOLANICH
Copy link

KOLANICH commented May 25, 2019

1 clone https://github.com/kaitai-io/kaitai_struct_formats (we abbreviate it as ksf in our discussions)
2 create a branch osu and switch to it
3 go to game dir and create an osu dir
4. dump your files there and give them names matching their ids
5. in order to include the stuff imports is used, it is either a path from ksf folder root or a path relative the current file dir, file extension is unneeded in imports
6. send a PR to ksf.

@takase1121
Copy link
Author

should i fork?

@KOLANICH
Copy link

yes

@takase1121
Copy link
Author

If i understood what you said correctly, this should be it
kaitai-io/kaitai_struct_formats#157

@KOLANICH
Copy link

Yeah, let[s have the further discussion in that PR.

@dgelessus
Copy link
Contributor

osu_ver is in main.ksy and the logic I posted is in Beatmap.ksy

I think this structure will not work here. _parent and _root will always stay inside the current ksy file, so you cannot use _parent in Beatmap.ksy to access fields from main.ksy. I think in this case you need to merge Beatmap.ksy into main.ksy (i. e. make beatmap a type inside main.ksy), then you can access fields "above" beatmap using _parent and _root.

@takase1121
Copy link
Author

@dgelessus
that is sure a pain. I will do that instead

@ams-tschoening
Copy link

I think in this case you need to merge Beatmap.ksy into main.ksy (i. e. make beatmap a type inside main.ksy), then you can access fields "above" beatmap using _parent and _root.

Parametric types might be a solution as well, those are designed to forward types to types and circumvent the concepts of implicit _parent and _root implemented currently.

#275 (comment)

@milahu

This comment was marked as outdated.

@generalmimon generalmimon changed the title Question: How can I do this? How to dynamically switch type based on a condition? Apr 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants