Конвертация пакета в perl6 - PullRequest
       12

Конвертация пакета в perl6

0 голосов
/ 18 ноября 2018

Я хотел бы преобразовать следующее из perl5 в perl6,

$salt = pack "C*", map {int rand 256} 1..16;

Создается строка из 16 символов, в которой каждый символ имеет произвольно выбранное значение от 0 до 255. Perl5 не присваивает этим символам никакой семантики, поэтому они могут быть байтами, кодовыми точками Unicode или чем-то еще.

Я думаю, что смогу обойтись с

$salt = (map {(^256).pick.chr},^16).join;

Но я застрял на использовании пакета, вот моя попытка,

use experimental :pack;

my $salt = pack("C*",(map {(^256).pick} , ^16)).decode('utf-8');

say $salt;
say $salt.WHAT;

и результаты могут быть либо ошибкой,

Malformed termination of UTF-8 string  
      in block <unit> at test.p6 line 3

или что-то вроде,

  j
  (Str)

Моя точка зрения заключается в том, что упаковка целого числа List вернет Buf , а затем декодирование, которое должно дать требуемые Str .

Обновление:

Как указано в комментарии и ответе Buf является правильным объектом для использования. Теперь, чтобы узнать о pack части,

perl6 -e 'use experimental :pack; my $salt = pack("C*",(map {(^256).pick} , ^16));say $salt;say $salt.WHAT;'

Buf: 0x <7D> (Buf)

, который упаковал только одну единицу

С другой стороны, использование P5pack (предложено Scimon) возвращает ошибку

perl6 -e 'use P5pack; my $salt = pack("C*",(map {(^256).pick} , ^16));say $salt;say $salt.WHAT;'
Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏*' (indicated by ⏏)
  in sub one at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 166
  in sub pack at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 210
  in block <unit> at -e line 1

Обновление 2:

Я не заметил разницу.

perl6 -e 'say (map {(^256).pick}, ^16).WHAT;'
(Seq)
perl6 -e 'say Buf.new((^256).roll(16)).WHAT;'  
(Buf)

Теперь составьте их списки,

perl6 -e 'use experimental :pack; my $salt = pack("C*",(Buf.new((^256).roll(16)).list));say $salt;say $salt.WHAT;'
    Buf:0x<39>
    (Buf)

И

perl6 -e 'use P5pack; my $salt = pack("C*",Buf.new((^256).roll(16)).list);say $salt;say $salt.WHAT;'
    Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏*' (indicated by ⏏)
      in sub one at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 166
      in sub pack at /home/david/.rakudobrew/moar-master/install/share/perl6/site/sources/D326BD5B05A67DBE51C279B9B9D9B448C6CDC401 (P5pack) line 210
      in block <unit> at -e line 1

Ссылка:

Буферы и двоичный ввод-вывод

Первый подход к упаковке / распаковке в Perl 6

Заранее спасибо за помощь.

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

Самый простой способ - это, вероятно, использовать https://modules.perl6.org/dist/P5pack:cpan:ELIZABETH, который позволяет использовать синтаксис пакета Perl5.

0 голосов
/ 26 ноября 2018

Видимо "C" x 16 работает, но не "C*".Не спрашивай, я тоже не знаю почему.: -D

perl6 -e 'use experimental :pack; my $salt = pack("C" x 16,(Buf.new((^256).roll(16)).list));say $salt;say $salt.WHAT;'
Buf:0x<64 71 D4 E6 E6 AD 7B 1C DD A2 62 CC DD DA F3 08>
(Buf)

С другой стороны, распаковка работает.

perl6 -e 'use experimental :pack; my $salt = pack("C" x 16,(Buf.new((^256).roll(16)).list)).unpack("C*");say $salt;say $salt.WHAT;'
(35 101 155 237 153 126 109 193 94 105 70 111 59 51 131 233)
(List)

В общем, ответ mscha - чистый и аккуратный.Это было глупое обратное путешествие в pack список Buf, чтобы получить Buf.

Что касается других преобразований пакета, обратите внимание на два ключевых момента из здесь ,

Here is the difference between Perl 5 and Perl 6 pack/unpack:

Perl 5                      Perl 6

pack(List)  --> Str         pack(List)  --> Buf
unpack(Str) --> List        unpack(Buf) --> List

И

некоторые шаблонные правила Perl 5 предполагают несложную улицу с двусторонним движением между Buf и Str.В Perl 5 просто нет реального различия между Buf и Str, и Perl 5 использует это совсем немного.

Редактировать: исправить опечатку, s / masha / mscha /;

0 голосов
/ 19 ноября 2018

Как сказал Икегами в комментарии к вашему вопросу, вам действительно следует использовать Buf, который по сути является «строкой» байтов.

my $salt = Buf.new((^256).roll(16));

Вы можете записать это в файл с чем-то вроде:

spurt 'foo', $salt, :bin;

или закодируйте его в base-64 с помощью:

use MIME::Base64;
my $encoded = MIME::Base64.encode($salt);

Но если вам нужно, чтобы это было достаточно безопасно, взгляните на Crypt :: Random

use Crypt::Random;
my $salt = crypt_random_buf(16);
...