make github the primary repository
[gitmo/Moose.git] / lib / Moose / Meta / Method / Accessor / Native / Hash / set.pm
index 6512d6c..3185f32 100644 (file)
@@ -3,25 +3,12 @@ package Moose::Meta::Method::Accessor::Native::Hash::set;
 use strict;
 use warnings;
 
+use List::MoreUtils ();
 use Scalar::Util qw( looks_like_number );
 
-our $VERSION = '1.15';
-$VERSION = eval $VERSION;
-our $AUTHORITY = 'cpan:STEVAN';
-
 use Moose::Role;
 
-with 'Moose::Meta::Method::Accessor::Native::Hash::Writer' => {
-    -excludes => [
-        qw(
-            _minimum_arguments
-            _maximum_arguments
-            _inline_process_arguments
-            _inline_check_arguments
-            _inline_optimized_set_new_value
-            )
-    ],
-};
+with 'Moose::Meta::Method::Accessor::Native::Hash::Writer';
 
 sub _minimum_arguments { 2 }
 
@@ -31,44 +18,89 @@ around _inline_check_argument_count => sub {
     my $orig = shift;
     my $self = shift;
 
-    return
-        $self->$orig(@_) . "\n"
-        . $self->_inline_throw_error(
-        q{'You must pass an even number of arguments to set'})
-        . ' if @_ % 2;';
+    return (
+        $self->$orig(@_),
+        'if (@_ % 2) {',
+            $self->_inline_throw_error(
+                sprintf(
+                    '"You must pass an even number of arguments to %s"',
+                    $self->delegate_to_method,
+                ),
+            ) . ';',
+        '}',
+    );
 };
 
 sub _inline_process_arguments {
     my $self = shift;
 
-    return 'my @keys_idx = grep { ! ($_ % 2) } 0..$#_;' . "\n"
-        . 'my @values_idx = grep { $_ % 2 } 0..$#_;';
+    return (
+        'my @keys_idx = grep { ! ($_ % 2) } 0..$#_;',
+        'my @values_idx = grep { $_ % 2 } 0..$#_;',
+    );
 }
 
 sub _inline_check_arguments {
     my $self = shift;
 
-    return
-        'for (@keys_idx) {' . "\n"
-        . $self->_inline_throw_error(
-        q{'Hash keys passed to set must be defined'})
-        . ' unless defined $_[$_];' . "\n" . '}';
+    return (
+        'for (@keys_idx) {',
+            'if (!defined($_[$_])) {',
+                $self->_inline_throw_error(
+                    sprintf(
+                        '"Hash keys passed to %s must be defined"',
+                        $self->delegate_to_method,
+                    ),
+                ) . ';',
+            '}',
+        '}',
+    );
 }
 
 sub _adds_members { 1 }
 
+# We need to override this because while @_ can be written to, we cannot write
+# directly to $_[1].
+sub _inline_coerce_new_values {
+    my $self = shift;
+
+    return unless $self->associated_attribute->should_coerce;
+
+    return unless $self->_tc_member_type_can_coerce;
+
+    # Is there a simpler way to do this?
+    return (
+        'my $iter = List::MoreUtils::natatime(2, @_);',
+        '@_ = ();',
+        'while (my ($key, $val) = $iter->()) {',
+            'push @_, $key, $member_coercion->($val);',
+        '}',
+    );
+};
+
 sub _potential_value {
-    my ( $self, $slot_access ) = @_;
+    my $self = shift;
+    my ($slot_access) = @_;
 
-    return "{ %{ $slot_access }, \@_ }";
+    return '{ %{ (' . $slot_access . ') }, @_ }';
 }
 
 sub _new_members { '@_[ @values_idx ]' }
 
 sub _inline_optimized_set_new_value {
-    my ( $self, $inv, $new, $slot_access ) = @_;
+    my $self = shift;
+    my ($inv, $new, $slot_access) = @_;
+
+    return '@{ (' . $slot_access . ') }{ @_[@keys_idx] } = @_[@values_idx];';
+}
+
+sub _return_value {
+    my $self = shift;
+    my ($slot_access) = @_;
 
-    return "\@{ $slot_access }{ \@_[ \@keys_idx] } = \@_[ \@values_idx ]";
+    return 'wantarray '
+             . '? @{ (' . $slot_access . ') }{ @_[@keys_idx] } '
+             . ': ' . $slot_access . '->{ $_[$keys_idx[0]] }';
 }
 
 no Moose::Role;