package Mock::Data::Generator;
use strict;
use warnings;
require MRO::Compat if "$]" < '5.009005';
require mro;
mro::set_mro(__PACKAGE__, 'c3');
require Scalar::Util;
require Carp;
our @CARP_NOT= qw( Mock::Data Mock::Data::Util );
# ABSTRACT: Utilities and optional base class for authoring generators
our $VERSION = '0.03'; # VERSION
sub generate { Carp::croak "Unimplemented" }
sub compile {
my ($self, @default_params)= @_;
# If no arguments, add a simple wrapper around ->generate
return sub { $self->generate(shift) } unless @default_params > 1;
return sub { $self->generate(shift, @default_params) };
}
our $_try_reverse;
sub combine_generator {
# if already recursed, return the original default combination
return Mock::Data::Set->new_uniform($_[1], $_[0]) if $_try_reverse;
# Call the peer's combine_generator in case it is overridden
local $_try_reverse= 1;
return $_[1]->combine_generator($_[0]);
}
require Mock::Data::Set;
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Mock::Data::Generator - Utilities and optional base class for authoring generators
=head1 DESCRIPTION
This package provides a set of utility methods for writing generators, and an optional
abstract base class. (a Generator does not need to inherit from this class)
=head1 GENERATORS
The most basic C<Mock::Data> generator is a simple coderef of the form
sub ( $mockdata, \%arguments, @arguments ) { ... }
which returns a literal data item, usually a scalar. A generator can also be any object
which has a L</generate> method. Using an object provides more flexibility to handle
cases where a user wants to combine generators.
=head1 METHODS
=head2 generate
my $data= $generator->generate($mockdata, \%named_params, @pos_params);
Like the coderef, this takes an instance of L<Mock::Data> as the first non-self argument,
followed by a hashref of named parameters, followed by arbitrary positional parameters after
that.
=head2 compile
my $callable= $generator->compile(@default_params);
Return a plain coderef that most optimally performs the generation for the C<@default_params>.
This implementation just wraps C<< $self->generate(@defaults) >> in a coderef. Subclasses
may provide more useful optimization.
The returned coderef takes one argument, of a L<Mock::Data> instance.
=head2 combine_generator
my $new_generator= $generator->combine_generator( $peer );
The default way to combine two generators is to create a new generator that selects each
child generator 50% of the time. For generators that define a collection of possible data,
it may be preferred to merge the collections in a manner different than a plain 50% split.
This method allows for that custom behavior.
=head2 clone
A generator that wants to perform special behavior when the C<Mock::Data> instance gets cloned
can implement this method. I can't think of any reason a generator should ever need this,
since the L<Mock::Data/generator_state> gets cloned. Lack of the method indicates the
generator doesn't need this feature.
=head1 AUTHOR
Michael Conrad <mike@nrdvana.net>
=head1 VERSION
version 0.03
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2021 by Michael Conrad.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut