+ - allow transfer of glob references
- allow loading of classes and packages from __DATA__
- allow transfer of scalar references
use Object::Remote::Null;
use Object::Remote::Handle;
use Object::Remote::CodeContainer;
+use Object::Remote::GlobProxy;
+use Object::Remote::GlobContainer;
use Object::Remote;
+use Symbol;
use IO::Handle;
use Module::Runtime qw(use_module);
use Scalar::Util qw(weaken blessed refaddr);
my $value = shift;
return \$value;
}
+ )->filter_json_single_key_object(
+ __glob_ref__ => sub {
+ my $glob_container = $self->_id_to_remote_object(@_);
+ my $handle = Symbol::gensym;
+ tie *$handle, 'Object::Remote::GlobProxy', $glob_container;
+ return $handle;
+ }
);
}
return +{ __remote_code__ => $id };
} elsif ($ref eq 'SCALAR') {
return +{ __scalar_ref__ => $$data };
+ } elsif ($ref eq 'GLOB') {
+ return +{ __glob_ref__ => $self->_local_object_to_id(
+ Object::Remote::GlobContainer->new(handle => $data)
+ ) };
} else {
die "Can't collapse reftype $ref";
}
--- /dev/null
+package Object::Remote::GlobContainer;
+use Moo;
+use FileHandle;
+
+has _handle => (is => 'ro', required => 1, init_arg => 'handle');
+
+sub AUTOLOAD {
+ my ($self, @args) = @_;
+ (my $method) = our $AUTOLOAD =~ m{::([^:]+)$};
+ return if $method eq 'DESTROY';
+ return $self->_handle->$method(@args);
+}
+
+1;
--- /dev/null
+use strictures 1;
+
+package Object::Remote::GlobProxy;
+require Tie::Handle;
+our @ISA = qw( Tie::Handle );
+
+sub TIEHANDLE {
+ my ($class, $glob_container) = @_;
+ return bless { container => $glob_container }, $class;
+}
+
+my @_delegate = (
+ [READLINE => sub { wantarray ? $_[0]->getlines : $_[0]->getline }],
+ (map { [uc($_), lc($_)] } qw(
+ write
+ print
+ printf
+ read
+ getc
+ close
+ open
+ binmode
+ eof
+ tell
+ seek
+ )),
+);
+
+for my $delegation (@_delegate) {
+ my ($from, $to) = @$delegation;
+ no strict 'refs';
+ *{join '::', __PACKAGE__, $from} = sub {
+ $_[0]->{container}->$to(@_[1 .. $#_]);
+ };
+}
+
+1;
--- /dev/null
+1
+2
+3
+4
+5
--- /dev/null
+package ORTestGlobs;
+use Moo;
+
+has handle => (is => 'rw');
+has valueref => (is => 'ro', default => sub {
+ my $body = '';
+ return \$body;
+});
+
+sub write { my $self = shift; print { $self->handle } @_ }
+
+sub getvalue { ${ $_[0]->valueref } }
+
+sub gethandle {
+ open my $fh, '>', $_[0]->valueref
+ or die "Unable to open in-memory file: $!\n";
+ return $fh;
+}
+
+sub getreadhandle {
+ open my $fh, '<', $_[1]
+ or die "Unable to open in-memory file: $!\n";
+ return $fh;
+}
+
+1;
use strictures 1;
use Test::More;
use Test::Fatal;
+use FindBin;
$ENV{PERL5LIB} = join(
':', ($ENV{PERL5LIB} ? $ENV{PERL5LIB} : ()), qw(lib t/lib)
is exception {
my $proxy = ORTestTransfer->new::on('-', value => \$strA);
is_deeply $proxy->value, \$strA, 'correct value after construction';
-}, undef, 'no errors during construction';
+}, undef, 'scalar refs - no errors during construction';
is exception {
my $proxy = ORTestTransfer->new::on('-');
$proxy->value(\$strB);
is_deeply $proxy->value, \$strB, 'correct value after construction';
-}, undef, 'no errors during attribute set';
+}, undef, 'scalar refs - no errors during attribute set';
+
+my $data_file = "$FindBin::Bin/data/numbers.txt";
+
+is exception {
+ my $out = '';
+ open my $fh, '>', \$out or die "Unable to open in-memory file: $!\n";
+ my $proxy = ORTestGlobs->new::on('-', handle => $fh);
+ ok $proxy->handle, 'filehandle was set';
+ ok $proxy->write('foo'), 'write was successful';
+ is $out, 'foo', 'write reached target';
+}, undef, 'filehandles - no error during construction';
+
+is exception {
+ my $proxy = ORTestGlobs->new::on('-');
+ my $handle = $proxy->gethandle;
+ print $handle 'foo';
+ is $proxy->getvalue, 'foo', 'correct value written';
+ $handle->autoflush(1);
+}, undef, 'filehandles - no error during remote handle';
+
+is exception {
+ my $proxy = ORTestGlobs->new::on('-');
+ my $rhandle = $proxy->getreadhandle($data_file);
+ my @lines = <$rhandle>;
+ chomp @lines;
+ is_deeply \@lines, [1 .. 5], 'reading back out of the handle';
+}, undef, 'filehandles - no error during remote read';
+
+is exception {
+ my $proxy = ORTestGlobs->new::on('-');
+ my $rhandle = $proxy->getreadhandle($data_file);
+ binmode $rhandle;
+}, undef, 'filehandles - no errors during binmode';
done_testing;