{"action":"created","issue":{"url":"https://api.github.com/repos/kaitai-io/kaitai_struct/issues/21","repository_url":"https://api.github.com/repos/kaitai-io/kaitai_struct","labels_url":"https://api.github.com/repos/kaitai-io/kaitai_struct/issues/21/labels{/name}","comments_url":"https://api.github.com/repos/kaitai-io/kaitai_struct/issues/21/comments","events_url":"https://api.github.com/repos/kaitai-io/kaitai_struct/issues/21/events","html_url":"https://github.com/kaitai-io/kaitai_struct/issues/21","id":171093480,"number":21,"title":"Perl support","user":{"login":"sergeyzelenyuk","id":20990054,"avatar_url":"https://avatars.githubusercontent.com/u/20990054?v=3","gravatar_id":"","url":"https://api.github.com/users/sergeyzelenyuk","html_url":"https://github.com/sergeyzelenyuk","followers_url":"https://api.github.com/users/sergeyzelenyuk/followers","following_url":"https://api.github.com/users/sergeyzelenyuk/following{/other_user}","gists_url":"https://api.github.com/users/sergeyzelenyuk/gists{/gist_id}","starred_url":"https://api.github.com/users/sergeyzelenyuk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sergeyzelenyuk/subscriptions","organizations_url":"https://api.github.com/users/sergeyzelenyuk/orgs","repos_url":"https://api.github.com/users/sergeyzelenyuk/repos","events_url":"https://api.github.com/users/sergeyzelenyuk/events{/privacy}","received_events_url":"https://api.github.com/users/sergeyzelenyuk/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/kaitai-io/kaitai_struct/labels/enhancement","name":"enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":34,"created_at":"2016-08-15T01:27:54Z","updated_at":"2016-08-27T14:09:09Z","closed_at":null,"body":"Hello, I've written a runtime for Perl, it's a draft without an usage example and tests, but it works. Please check it: https://github.com/sergeyzelenyuk/kaitai_struct_perl_runtime."},"comment":{"url":"https://api.github.com/repos/kaitai-io/kaitai_struct/issues/comments/242919278","html_url":"https://github.com/kaitai-io/kaitai_struct/issues/21#issuecomment-242919278","issue_url":"https://api.github.com/repos/kaitai-io/kaitai_struct/issues/21","id":242919278,"user":{"login":"sergeyzelenyuk","id":20990054,"avatar_url":"https://avatars.githubusercontent.com/u/20990054?v=3","gravatar_id":"","url":"https://api.github.com/users/sergeyzelenyuk","html_url":"https://github.com/sergeyzelenyuk","followers_url":"https://api.github.com/users/sergeyzelenyuk/followers","following_url":"https://api.github.com/users/sergeyzelenyuk/following{/other_user}","gists_url":"https://api.github.com/users/sergeyzelenyuk/gists{/gist_id}","starred_url":"https://api.github.com/users/sergeyzelenyuk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sergeyzelenyuk/subscriptions","organizations_url":"https://api.github.com/users/sergeyzelenyuk/orgs","repos_url":"https://api.github.com/users/sergeyzelenyuk/repos","events_url":"https://api.github.com/users/sergeyzelenyuk/events{/privacy}","received_events_url":"https://api.github.com/users/sergeyzelenyuk/received_events","type":"User","site_admin":false},"created_at":"2016-08-27T14:09:09Z","updated_at":"2016-08-27T14:09:09Z","body":"Good, it works. The next moment I faced is enums, Perl doesn't have this type. I've tried several ways to implement it, here are the best of them:\r\n\r\n1. Use hashes:\r\n\r\n```perl\r\nmy $ANIMAL = {\r\n    4 => 'dog',\r\n    7 => 'cat',\r\n    12 => 'chicken',\r\n};\r\n```\r\n\r\nIt's ok but not enough because we can't specify that 'dog' or 'cat' are possible ANIMAL values, they are only strings:\r\n\r\n```perl\r\nis($r->{pet_1}, 'cat', 'Equals');\r\nis($r->{pet_2}, 'chicken', 'Equals');\r\n```\r\n\r\n2. Use hashes + static method:\r\n\r\n```perl\r\npackage Enum0;\r\n\r\nmy $ANIMAL = {\r\n    4 => 'dog',\r\n    7 => 'cat',\r\n    12 => 'chicken',\r\n};\r\n\r\nsub animal {\r\n    my $enum = shift;\r\n\r\n    my $key = $ANIMAL->{$enum};\r\n    return $key if defined $key; # Number passed\r\n\r\n    my $value = %{{reverse %{$ANIMAL}}}{\"$enum\"};\r\n    return $enum if defined $value; # String passed\r\n\r\n    return undef;\r\n}\r\n```\r\n\r\nTo convert numbers to enum values (strings) we call that method with numbers as input:\r\n\r\n```perl\r\n$self->{pet_1} = animal($self->{_io}->read_u4le());\r\n$self->{pet_2} = animal($self->{_io}->read_u4le());\r\n```\r\n\r\nTo test it we call `animal` method with strings as input. If they are valid `ANIMAL` values the method will simply return string back and if they aren't the method return `undef`:\r\n\r\n```perl \r\nis($r->{pet_1}, Enum0::animal('cat'), 'Equals');        # ok: pet_1 == 'cat'\r\nis($r->{pet_2}, Enum0::animal('chicken'), 'Equals');    # ok: pet_2 == 'chicken'\r\nis($r->{pet_2}, Enum0::animal('camel'), 'Equals');      # fail: pet_2 != undef\r\n```\r\n\r\nThe only drawback is we must put `ANIMAL` hash and `animal` method into one of packages and use this method appropriately. I think the better way is to put them into \"head\" packages of each module, for example, into `Enum0` package of `Enum0.pm` module and into `EnumIf` package into `EnumIf.pm` module.\r\n\r\nWhat do you think? If you are agree with me I'll post diff files for `Enum0.pm` and `EnumIf.pm` here."}}
{"actor":{"display_login":"sergeyzelenyuk"}}