Hash-Wrap

 view release on metacpan or  search on metacpan

lib/Hash/Wrap.pm  view on Meta::CPAN


        if ( keys %$args ) {
            _croak( 'unknown options passed to ', __PACKAGE__, '::import: ', join( ', ', keys %$args ) );
        }
    }

    return @return;
}

sub _build_class {    ## no critic(ExcessComplexity)
    my ( $target, $name, $attr ) = @_;

    # in case we're called inside a recursion and the recurse count
    # has hit zero, default behavior is no recurse, so remove it so
    # the attr signature computed below isn't contaminated by a
    # useless -recurse => 0 attribute.
    if ( exists $attr->{-recurse} ) {
        _croak( '-recurse must be a number' )
          unless Scalar::Util::looks_like_number( $attr->{-recurse} );
        delete $attr->{-recurse} if $attr->{-recurse} == 0;
    }

    if ( !defined $attr->{-class} ) {

        ## no critic (ComplexMappings)
        my @class = map {
            ( my $key = $_ ) =~ s/-//;
            ( $key, defined $attr->{$_} ? $attr->{$_} : '<undef>' )
        } sort keys %$attr;

        $attr->{-class} = join q{::}, 'Hash::Wrap::Class', Digest::MD5::md5_hex( @class );
    }

    elsif ( $attr->{-class} eq '-target' || $attr->{-class} eq '-caller' ) {
        _croak( "can't set -class => '@{[ $attr->{-class} ]}' if '-as' is not a plain string" )
          if ref $name;
        $attr->{-class} = $target . q{::} . $name;
    }

    my $class = $attr->{-class};

    return $class if defined $REGISTRY{$class};
    my $rentry = $REGISTRY{$class} = { methods => {} };

    my %closures;
    my @BODY;
    my %dict = (
        class                 => $class,
        signature             => q{},
        body                  => \@BODY,
        autoload_attr         => q{},
        validate_inline       => 'exists $self->{\<<KEY>>}',
        validate_method       => 'exists $self->{$key}',
        set                   => '$self->{q[\<<KEY>>]} = $_[0] if @_;',
        return_value          => '$self->{q[\<<KEY>>]}',
        recursion_constructor => q{},
        predicate_template    => q{},
    );

    if ( $attr->{-lvalue} ) {
        if ( $] lt '5.016000' ) {
            _croak( 'lvalue accessors require Perl 5.16 or later' )
              if $attr->{-lvalue} < 0;
        }
        else {
            $dict{autoload_attr} = q[: lvalue];
            $dict{signature}     = q[: lvalue];
        }
    }

    if ( $attr->{-undef} ) {
        $dict{validate_method} = q[ 1 ];
        $dict{validate_inline} = q[ 1 ];
    }

    if ( $attr->{-exists} ) {
        $dict{exists} = $attr->{-exists} =~ PerlIdentifier ? $1 : 'exists';
        push @BODY, q[ sub <<EXISTS>> { exists $_[0]->{$_[1] } } ];
        $rentry->{methods}{ $dict{exists} } = undef;
    }

    if ( $attr->{-defined} ) {
        $dict{defined} = $attr->{-defined} =~ PerlIdentifier ? $1 : 'defined';
        push @BODY, q[ sub <<DEFINED>> { defined $_[0]->{$_[1] } } ];
        $rentry->{methods}{ $dict{defined} } = undef;
    }

    if ( $attr->{-immutable} ) {
        $dict{set} = <<'END';
  Hash::Wrap::_croak( q[Modification of a read-only value attempted])
    if @_;
END
    }

    if ( $attr->{-recurse} ) {

        # decrement recursion limit.  It's infinite recursion if
        # -recurse < 0; always set to -1 so we keep using the same
        # class.  Note that -recurse will never be zero upon entrance
        # of this block, as -recurse => 0 is removed from the
        # attributes way upstream.

        $dict{recurse_limit} = --$attr->{-recurse} < 0 ? -1 : $attr->{-recurse};

        $dict{quoted_key} = 'q[\<<KEY>>]';
        $dict{hash_value} = '$self->{<<QUOTED_KEY>>}';

        $dict{recurse_wrap_hash} = '$<<CLASS>>::recurse_into_hash->( <<HASH_VALUE>> )';

        $dict{return_value} = <<'END';
 'HASH' eq (Scalar::Util::reftype( <<HASH_VALUE>> ) // q{})
        && ! Scalar::Util::blessed( <<HASH_VALUE>> )
      ? <<WRAP_HASH_ENTRY>>
      : <<HASH_VALUE>>;
END
        if ( $attr->{-copy} ) {

            if ( $attr->{-immutable} ) {
                $dict{wrap_hash_entry} = <<'END';
                 do { Hash::Util::unlock_ref_value( $self, <<QUOTED_KEY>> );
                      <<HASH_VALUE>> = <<RECURSE_WRAP_HASH>>;



( run in 1.591 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )