将包转换为perl6

时间:2018-11-18 20:26:20

标签: perl6 raku

我想将以下内容从perl5转换为perl6,

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

它将创建一个由16个字符组成的字符串,其中每个字符都有一个从0到255的随机选取值。Perl5不会为这些字符分配任何语义,因此它们可以是字节,Unicode代码点或其他。

我想我可以和

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

但是我在使用pack时遇到问题,这是我的尝试,

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;'

缓冲区: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

参考:

Buffers and Binary IO

A first approach to pack/unpack in Perl 6

预先感谢您的帮助。

3 个答案:

答案 0 :(得分:8)

就像池上在对您的问题的评论中说的那样,您确实应该使用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);

答案 1 :(得分:5)

最简单的方法是使用https://modules.perl6.org/dist/P5pack:cpan:ELIZABETH,它允许您使用Perl5 pack语法。

答案 2 :(得分:2)

显然"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的回答是P6'ish整洁。到pack的{​​{1}}列表中获取Buf很愚蠢。

对于其他包装转换,请注意here中的两个关键点,

Buf

一些Perl 5模板规则假定Buf和Str之间没有复杂的双向道路。在Perl 5中,Buf和Str之间根本没有真正的区别,而Perl 5充分利用了这一点。

编辑:修正错字,s / masha / mscha /;