package Data::QRCode; use Moo; use Data::QRCode::Input; use Data::QRCode::Result; use Data::QRCode::Types qw(QRCodeEC QRCodeMode); use Types::Standard qw(Str Int); use namespace::clean; # ABSTRACT: qrcodes in C # VERSION =head1 SYNOPSIS use Data::QRCode; my $qr = Data::QRCode->new('some string'); my $text_matrix = $qr->map( sub { $_[0]->{color} ? '*' : ' ' } ); print "$_\n" for map { join '',@{$_} } @{$text_matrix}; =head1 DESCRIPTION This class exposes a simple interface to the L<< C|http://fukuchi.org/works/qrencode/index.html.en >> library. =attr C =cut has error_correction_level => ( is => 'ro', isa => QRCodeEC, coerce => 1, default => Data::QRCode::Input::ECLEVEL_M, ); =attr C =cut has mode => ( is => 'ro', isa => QRCodeMode, coerce => 1, default => Data::QRCode::Input::MODE_8, ); =attr C =cut has version => ( is => 'rwp', isa => Int, default => 0, ); =attr C =for Pod::Coverage BUILDARGS =cut has input_data => ( is => 'ro', required => 1, isa => Str, ); around BUILDARGS => sub { my ($orig,$class,@args) = @_; return { input_data => $args[0] } if @args == 1 && !ref $args[0]; return $class->$orig(@args); }; has _result => ( is => 'lazy', init_arg => undef, handles => [ qw(width data_at) ], ); sub _build__result { ## no critic(ProhibitUnusedPrivateSubroutines) my ($self) = @_; my $input = Data::QRCode::Input->new(); $input->error_correction_level($self->error_correction_level); $input->version($self->version); $input->append($self->mode,$self->input_data); my $ret = Data::QRCode::Result->new($input); $self->_set_version($ret->version); return $ret; } =method C =cut sub map { ## no critic(ProhibitBuiltinHomonyms) my ($self,$code) = @_; my $r = $self->_result; my @result; for my $y (0..$r->width-1) { push @result,[]; for my $x (0..$r->width-1) { # use the internal function to avoid re-checking the x/y # bounds my $raw_data = $r->_data_at($x,$y); my $hash_data = Data::QRCode::Result::_data_hash($raw_data); ## no critic(ProtectPrivateSubs) push @{$result[-1]}, $code->($hash_data,$raw_data); } } return \@result; } 1;