| Class-Serializer documentation | Contained in the Class-Serializer distribution. |
Class::Serializer - Serializes the in-memory state of a class into code
Version 0.03
This module does its best efforts to serialize the in-memory state of a class into runable code. For this to actually happen successfully it relies heavily on Data::Dump::Streamer which, in turn, relies on B::Deparse for CODEREF deparsing and other similar tasks.
Please, keep in mind that this module is experimental. There are no guarantees whatsoever about the generated code.
With that said, it should work just fine.
Here's a little a code snippet:
use Class::Serializer;
# Class::Serializer is Class::Serializer safe
my $class_code = Class::Serializer->as_string('Class::Serializer');
# writes directly to ClassSerializer.pm
Class::Serializer->as_file(Class::Serializer => 'ClassSerializer.pm');
Serializes $target_class in-memory state (actually, symbol table entries)
into perl code and returns it as a string. It will also try to detect possible
dependencies and try to honor them through require statements in the
generated code.
Serializes $target_class in-memory state into perl code and saves it into
$file_name, overwriting the file if $overwrite is set to a true value.
If $file_name is not defined, it will be constructed based on the target
class name, relative do the current path. So Class::Serializer would be saved
in Class/Serializer.pm.
If $file_name exists and $overwrite is not set, an exception is thrown.
An exception is also thrown if the file is not writable.
The dependency detecting code is pretty simple and may be not very reliable.
Closures should work just fine as of version 0.03. This feature wasn't tested extensively, though (it just relies on Data::Dump::Streamer for that).
Nilson Santos Figueiredo Júnior, <nilsonsfj at cpan.org>
Please report any bugs or feature requests directly to the author. If you ask nicely it will probably get fixed or implemented.
You can also look for information at:
Copyright 2008 Nilson Santos Figueiredo Júnior, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Class-Serializer documentation | Contained in the Class-Serializer distribution. |
package Class::Serializer; use warnings; use strict; # no imports, thanks use File::Path (); use Data::Dump::Streamer ();
our $VERSION = '0.03';
sub as_string { my $class = shift; my ($target) = @_; my %seen; no strict 'refs'; # loads the relevant data structures while (my ($entry, $contents) = each %{"${target}::"}) { for my $type (qw|SCALAR ARRAY HASH CODE|) { if (*{$contents}{$type}) { next if ($type eq 'SCALAR' && !defined ${*{$contents}{$type}}); push(@{$seen{$type}}, ["$entry", *{$contents}{$type}]); } } }; use strict 'refs'; # builds up something suitable to be spoon fed to the dumper my (@dump, @names); for my $type (qw|ARRAY HASH CODE|) { for my $entry (@{$seen{$type}}) { push(@dump, $entry->[1]); push(@names, '*'.$entry->[0]); } } # Data::Dumper messes everything up with scalars for my $entry (@{$seen{SCALAR}}) { push(@dump, ${$entry->[1]}); push(@names, '$'.$entry->[0]); } my $dump = "package $target;\n" . Data::Dump::Streamer::DumpVars( map { $names[$_], $dump[$_] } 0..$#dump )->Declare(1)->Out() . ';1;'; my %required = ($target => 1); # tries to detect dependencies and loads them through eval 'require Pkg' # (eval is used so that errors are not fatal) my $require = ''; while ($dump =~ /(?:package ([\w\:]+);|'([\w\:]+)'\->)/g) { my $pkg = $1 || $2; unless ($required{$pkg}) { $require .= "eval 'require $pkg';\n"; $required{$pkg} = 1; } } $require . $dump; }
sub as_file { my $class = shift; my ($target, $file_name, $overwrite) = @_; # constructs the file name, if it's either undef or empty unless (defined $file_name && length($file_name)) { ($file_name = $target) =~ s|::|/|; $file_name .= '.pm'; } # creates directories if they don't exist if ((my $path = $file_name) =~ s|([\\/])[^\\/]+$|$1|) { File::Path::mkpath($path); } _croak("'$file_name' already exists") if (-e $file_name && !$overwrite); # writes open(my $fh, '>', $file_name) or _croak("couldn't write to '$file_name': $!"); print $fh $class->as_string($target); close $fh; $file_name; } sub _croak { require Carp; Carp::croak(@_); }
1; # End of Class::Serializer