sub some_attribute {
my $self = shift;
$self->{some_attribute} = shift if @_;
return $self->{some_attribute};
}
####
has some_attribute => (is => 'rw');
##
##
{
package Binary::Humax::HmtData;
use DateTime;
use Moose;
has raw_data_block => (
is => 'rw',
isa => 'Str',
required => 1,
);
# Shortcut function for defining attributes
#
sub _my_has
{
my ($name, %spec) = @_;
my $meta = __PACKAGE__->meta;
# Default attribute to 'rw'
$spec{is} //= 'rw';
# Set up lazy builder
if (my $unpack = delete $spec{unpack})
{
$spec{lazy} //= 1;
$spec{builder} //= "_build_$name";
if (my $postprocess = delete $spec{postprocess})
{
$meta->add_method($spec{builder}, sub {
my $self = shift;
local $_ = unpack($unpack, $self->raw_data_block);
$postprocess->();
});
}
else
{
$meta->add_method($spec{builder}, sub {
my $self = shift;
return unpack($unpack, $self->raw_data_block);
});
}
}
$meta->add_attribute($name, \%spec);
}
# Now use that shortcut to define each attribute.
#
_my_has last_play => (isa => 'Int', unpack => '@5 S');
_my_has chan_num => (isa => 'Int', unpack => '@17 S');
_my_has start_time => (
isa => 'DateTime',
unpack => '@5 S',
postprocess => sub {
DateTime->from_epoch(epoch => $_, time_zone => 'GMT');
},
);
_my_has file_name => (isa => 'Str', unpack => '@33 A512');
# Create an alternative constructor which wraps "new".
#
sub new_from_file
{
my ($class, $filename) = @_;
open my $fh, '>', $filename;
my $slurp = do { local $/ = <$fh> };
return $class->new(r);
}
}
#
# USAGE
#
my $hmt_data = Binary::Humax::HmtData->new_from_file($path_name);
my $field = $hmt_data->start_time;
##
##
{
package Binary::Humax::HmtData::Trait::Attribute;
use Moose::Role;
has unpack => (is => 'ro', isa => 'Str');
has postprocess => (is => 'ro', isa => 'CodeRef');
before _process_options => sub
{
my ($meta, $name, $spec) = @_;
if ($spec->{unpack})
{
$spec->{lazy} //= 1;
$spec->{builder} //= "_build_$name";
$spec->{is} //= 'rw';
}
};
after attach_to_class => sub
{
my $attr = shift;
my $class = $attr->associated_class;
my $unpack = $attr->unpack or return;
if (my $postprocess = $attr->postprocess)
{
$class->add_method($attr->builder, sub {
my $self = shift;
local $_ = unpack($unpack, $self->raw_data_block);
$postprocess->();
});
}
else
{
$class->add_method($attr->builder, sub {
my $self = shift;
return unpack($unpack, $self->raw_data_block);
});
}
};
}
{
package Binary::Humax::HmtData;
use DateTime;
use Moose;
use constant MAGIC => 'Binary::Humax::HmtData::Trait::Attribute';
has raw_data_block => (
is => 'rw',
isa => 'Str',
required => 1,
);
has last_play => (
traits => [ MAGIC ],
isa => 'Int',
unpack => '@5 S',
);
has chan_num => (
traits => [ MAGIC ],
isa => 'Int',
unpack => '@17 S',
);
has start_time => (
traits => [ MAGIC ],
isa => 'DateTime',
unpack => '@5 S',
postprocess => sub {
DateTime->from_epoch(epoch => $_, time_zone => 'GMT');
},
);
has file_name => (
traits => [ MAGIC ],
isa => 'Str',
unpack => '@33 A512',
);
}
# Attribute introspection
print Binary::Humax::HmtData->meta->get_attribute('start_time')->unpack, "\n";