#! /usr/bin/perl use strict; use warnings; package Class::InsideOut; use Attribute::Handlers; use NEXT; use Scalar::Util 1.09 qw(blessed refaddr); our $VERSION = 0.01; sub self { refaddr shift }; my %Values; sub Field : ATTR(HASH) { my ($class, $symbol, $hash) = @_; my $values = $Values{$class} ||= []; push @{$values}, $hash; }; sub DESTROY { my $self = $_[0]; my $id = $self->self; while ( my ($class, $values) = each %Values ) { delete $_->{$id} foreach (@$values); }; $self->NEXT::DESTROY() }; package Class::InsideOut::YAML; sub yaml_dump { my $item = shift; my $class = ref $item; my $self_id = $item->self; my $inverted = {}; while (my ($class, $values) = each %Values) { my $class_fields = $inverted->{$class} ||= []; foreach my $field (@$values) { push @$class_fields, $field->{$self_id}; }; delete $inverted->{$class} unless @$class_fields; }; my $ynode = YAML::Node->new({}, "perl/$class"); $ynode->{class} = $class; $ynode->{object} = bless Storable::dclone($item), 'Class::InsideOut::Frozen'; $ynode->{inverted} = $inverted; return($ynode); }; sub yaml_load { my $ynode = shift; my $self = bless $ynode->{object}, $ynode->{class}; my $inverted = $ynode->{inverted}; my $self_id = $self->self; while (my ($class, $values) = each %$inverted) { my $i = 0; foreach my $value (@$values) { $Values{$class}->[$i++]->{$self_id} = $value; }; }; return(bless $self, $ynode->{class}); }; 1;