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);
The easiest way is to probably to use https://modules.perl6.org/dist/P5pack:cpan:ELIZABETH which allows you to use Perl5 pack syntax.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With