Converting pack to perl6

  • A+
Category:Languages

I would like to convert the following from perl5 to perl6,

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

It create a string of 16 characters where each character has a randomly picked value from 0 to 255. Perl5 doesn't assign any semantics to those characters, so they could be bytes, Unicode Code Points, or something else.

I think I can get by with

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

But I got stuck on using pack, here is my attempt,

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

and results can be either an error,

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

or something like,

  j   (Str) 

My line of thought is that packing the integer List would return a Buf then decoding that should produce the required Str.

Update:

As suggested on comment and answer Buf is the correct object to use. Now to follow up on the pack part,

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

Buf:0x<7D> (Buf)

that only packed one unit

On the other hand, using P5pack (suggested by Scimon) returns an error

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 

Update 2:

I didn't spot the difference.

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

Now make them lists,

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

And

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 

Reference:

Buffers and Binary IO

A first approach to pack/unpack in Perl 6

Thanks in advance for the help.

 


As ikegami says in a comment to your question, you really should use a Buf, which is basically a “string” of bytes.

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

You can write this to a file with something like:

spurt 'foo', $salt, :bin; 

or encode it in base-64 with:

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

But if you need this to be reasonably secure, have a look at Crypt::Random

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

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: