У меня возникают трудности с правильным использованием MooseX::Declare при вызове BUILDARGS.
Я пытаюсь создать объект как интерфейс для файла. (В частности, мне нужен интерфейс для двоичного файла, который позволяет мне просмотреть следующие несколько байтов в файле, а затем отрезать их для дальнейшей обработки.)
Я хочу иметь возможность создать один из этих объектов, подобных этому
my $f = binary_file_buffer->new( $file_name );
а затем использовать его так
while( my $block_id = $f->peek( $id_offset, $id_length ) ) {
$block_id = unpack_block_id( $block_id );
$munge_block{ $block_id }->(
$f->pop( $block_size[ $block_id ] )
);
}
Мое определение/объявление класса binary_file_buffer выглядит следующим образом
use MooseX::Declare;
class binary_file_buffer {
use FileHandle;
use Carp;
has _file => ( is => 'ro', isa => 'FileHandle' );
has _file_name => ( is => 'ro', isa => 'Str' );
has _buff => ( is => 'rw', isa => 'Str', default => '' );
method BUILDARGS ( Str $file_name ) {
my $file = FileHandle->new( $file_name );
carp "unable to open $file_name : $!" unless defined $file;
$file->binmode;
return (
_file_name => $file_name,
_file => $file,
);
}
# get the next n bytes from the buffer.
method pop ( Int $len ) {
# ... Make sure there is data in _buff
return substr( $self->{_buff}, 0, $len, '' );
}
# Look around inside the buffer without changing the location for pop
method peek ( Int $offset, Int $len ) {
# ... Make sure there is data in _buff
return substr( $self->{_buff}, $offset, $len );
}
}
(Есть код загрузки буфера и управления, который я здесь не включил. Это довольно прямолинейно.)
Проблема в том, что я использую ключевое слово method
в объявлении BUILDARGS
. Таким образом, MooseX::Declare ожидает объект binary_file_buffer
в качестве первого аргумента для BUILDARGS
. Но BUILDARGS
получает аргументы, передаваемые в new, поэтому первым аргументом является строка a 'binary_file_buffer'
, имя пакета. В результате он не проходит проверку типов и умирает при создании объекта с помощью new, как я сделал в первом фрагменте кода. (По крайней мере, так я понимаю происходящее.)
Сообщение об ошибке, которое я получаю:
Validation failed for 'MooseX::Types::Structured::Tuple[MooseX::Types::Structured::Tuple[Object,Str,Bool],MooseX::Types::Structured::Dict[]]' failed with value [ [ "binary_file_buffer", "drap_iono_t1.log", 0 ], { } ], Internal Validation Error is: Validation failed for 'MooseX::Types::Structured::Tuple[Object,Str,Bool]' failed with value [ "binary_file_buffer", "drap_iono_t1.log", 0 ] at C:/bin/perl/site/lib/MooseX/Method/Signatures/Meta/Method.pm line 445
MooseX::Method::Signatures::Meta::Method::validate('MooseX::Method::Signatures::Meta::Method=HASH(0x2a623b4)', 'ARRAY(0x2a62764)') called at C:/bin/perl/site/lib/MooseX/Method/Signatures/Meta/Method.pm line 145
binary_file_buffer::BUILDARGS('binary_file_buffer', 'drap_iono_t1.log') called at generated method (unknown origin) line 5
binary_file_buffer::new('binary_file_buffer', 'drap_iono_t1.log') called at logshred.pl line 13
Мне нравится сахар проверки типов, который ключевое слово method
предоставляет для $file_name, но я не знаю, как его получить, поскольку BUILDARGS
технически не является методом.
Есть ли в MooseX::Declare способ пропустить создание $self
или что-то в этом роде?
Правильно ли я делаю MooseX::Declare? Или я что-то упускаю?