'Best' => '0', # << this if for loading YAML
# and the ability to save the
# file to disk
- 'IO::File' => '0',
+ 'IO::File' => '0',
+ # this if for the basic role with checksum
+ 'Digest::MD5' => '0',
+ 'Data::Dumper' => '0',
},
optional => {
'IO::AtomicFile' => '0',
Revision history for MooseX-Storage
0.02
+ * MooseX::Storage::Base::WithChecksum
+ - added a simple base role which makes a checksum of
+ the data structure before packing, and checks the
+ checksum before unpacking.
+ - added tests for this
+
* MooseX::Storage::Engine
- better error reporting when cycles are found
- class names are now stored as the full identifier
README
lib/MooseX/Storage.pm
lib/MooseX/Storage/Basic.pm
+lib/MooseX/Storage/Base/WithChecksum.pm
lib/MooseX/Storage/Engine.pm
lib/MooseX/Storage/Engine/IO/AtomicFile.pm
lib/MooseX/Storage/Engine/IO/File.pm
t/005_w_versions_and_authority_check.t
t/010_basic_json.t
t/020_basic_yaml.t
+t/030_with_checksum.t
t/100_io.t
t/101_io_atomic.t
t/pod-coverage.t
$pkg->meta->alias_method('Storage' => sub {
my %params = @_;
- $params{'base'} ||= 'Basic';
+ if (exists $params{'base'}) {
+ $params{'base'} = ('Base::' . $params{'base'});
+ }
+ else {
+ $params{'base'} = 'Basic';
+ }
my @roles = (
('MooseX::Storage::' . $params{'base'}),
--- /dev/null
+
+package MooseX::Storage::Base::WithChecksum;
+use Moose::Role;
+
+use Digest::MD5 ('md5_hex');
+use Data::Dumper ();
+use MooseX::Storage::Engine;
+
+our $VERSION = '0.01';
+
+sub pack {
+ my ($self, $salt) = @_;
+ my $e = MooseX::Storage::Engine->new( object => $self );
+ my $collapsed = $e->collapse_object;
+
+ # create checksum
+
+ local $Data::Dumper::Sortkeys = 1;
+ my $dumped = Data::Dumper::Dumper($collapsed);
+
+ #warn $dumped;
+
+ $salt ||= $dumped;
+
+ $collapsed->{checksum} = md5_hex($dumped, $salt);
+
+ return $collapsed;
+}
+
+sub unpack {
+ my ($class, $data, $salt) = @_;
+
+ # check checksum on data
+
+ my $old_checksum = $data->{checksum};
+ delete $data->{checksum};
+
+ local $Data::Dumper::Sortkeys = 1;
+ my $dumped = Data::Dumper::Dumper($data);
+
+ #warn $dumped;
+
+ $salt ||= $dumped;
+
+ my $checksum = md5_hex($dumped, $salt);
+
+ ($checksum eq $old_checksum)
+ || confess "Bad Checksum got=($checksum) expected=($data->{checksum})";
+
+ my $e = MooseX::Storage::Engine->new(class => $class);
+ $class->new($e->expand_object($data));
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+MooseX::Storage::Base::WithChecksum
+
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=over 4
+
+=item B<pack (?$salt)>
+
+=item B<unpack ($data, ?$salt)>
+
+=back
+
+=head2 Introspection
+
+=over 4
+
+=item B<meta>
+
+=back
+
+=head1 BUGS
+
+All complex software has bugs lurking in it, and this module is no
+exception. If you find a bug please either email me, or add the bug
+to cpan-RT.
+
+=head1 AUTHOR
+
+Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2007 by Infinity Interactive, Inc.
+
+L<http://www.iinteractive.com>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
},
collapse => sub {
my $obj = shift;
- ($obj->can('does') && $obj->does('MooseX::Storage::Basic'))
- || confess "Bad object ($obj) does not do MooseX::Storage::Basic role";
+# ($obj->can('does') && $obj->does('MooseX::Storage::Basic'))
+# || confess "Bad object ($obj) does not do MooseX::Storage::Basic role";
$obj->pack();
},
);
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 6;
+use Test::Exception;
+use Test::Deep;
+
+BEGIN {
+ use_ok('MooseX::Storage');
+}
+
+{
+
+ package Foo;
+ use Moose;
+ use MooseX::Storage;
+
+ with Storage(base => 'WithChecksum');
+
+ has 'number' => ( is => 'ro', isa => 'Int' );
+ has 'string' => ( is => 'ro', isa => 'Str' );
+ has 'float' => ( is => 'ro', isa => 'Num' );
+ has 'array' => ( is => 'ro', isa => 'ArrayRef' );
+ has 'hash' => ( is => 'ro', isa => 'HashRef' );
+ has 'object' => ( is => 'ro', isa => 'Foo' );
+}
+
+{
+ my $foo = Foo->new(
+ number => 10,
+ string => 'foo',
+ float => 10.5,
+ array => [ 1 .. 10 ],
+ hash => { map { $_ => undef } ( 1 .. 10 ) },
+ object => Foo->new( number => 2 ),
+ );
+ isa_ok( $foo, 'Foo' );
+
+ my $packed = $foo->pack;
+
+ cmp_deeply(
+ $packed,
+ {
+ __CLASS__ => 'Foo',
+ checksum => re('[0-9a-f]+'),
+ number => 10,
+ string => 'foo',
+ float => 10.5,
+ array => [ 1 .. 10 ],
+ hash => { map { $_ => undef } ( 1 .. 10 ) },
+ object => {
+ __CLASS__ => 'Foo',
+ checksum => re('[0-9a-f]+'),
+ number => 2
+ },
+ },
+ '... got the right frozen class'
+ );
+
+ my $foo2;
+ lives_ok {
+ $foo2 = Foo->unpack($packed);
+ } '... unpacked okay';
+ isa_ok($foo2, 'Foo');
+
+ cmp_deeply(
+ $foo2->pack,
+ {
+ __CLASS__ => 'Foo',
+ checksum => re('[0-9a-f]+'),
+ number => 10,
+ string => 'foo',
+ float => 10.5,
+ array => [ 1 .. 10 ],
+ hash => { map { $_ => undef } ( 1 .. 10 ) },
+ object => {
+ __CLASS__ => 'Foo',
+ checksum => re('[0-9a-f]+'),
+ number => 2
+ },
+ },
+ '... got the right frozen class'
+ );
+
+}
+