=pod

=head1 NAME

Class::Enumeration::Builder - Builder module for enum classes

=head1 SYNOPSIS

  # Setup enum class in a separate module and build it at compile time
  use strict;
  use warnings;
  use feature 'state';

  package TrafficLight;

  # Pre-declare the to_string() method to prepare overriding stringification
  use subs 'to_string';

  # The 'counter' option overwrites the default ordinal number generator
  # 'action' is a custom attribute
  use Class::Enumeration::Builder (
    { counter => sub { state $i = 0; my $r = $i; $i += 2; $r } },
    GREEN  => { action => 'go' },
    ORANGE => { action => 'slow down' },
    RED    => { action => 'stop' }
  );

  sub to_string {
    my ( $self ) = @_;

    $self->action . ' if ' . $self->name
  }

  1

  # Build enum class at compile time and export enum constants
  use strict;
  use warnings;

  package ToastStatus;

  # Choose an exporter module and set the 'export' option to true
  use Exporter qw( import );
  use Class::Enumeration::Builder
    { export => 1 },
    qw( bread toasting toast burnt );

  1

  # Build enum class at runtime
  my $class = Class::Enumeration::Builder->import(
    { class => 'CoffeeSize' },
    BIG          => { ounces => 8 },
    HUGE         => { ounces => 10 },
    OVERWHELMING => { ounces => 16 }
  );

=head1 DESCRIPTION

C<Class::Enumration::Builder> builds enum classes. Each such class will be a
child class of the abstract parent class L<Class::Enumeration>.  The builder
prepares a list of enum objects. It optionally creates getters for custom
attributes for each such object.

The C<import()> class method implements the build process.  The method returns
the name of the enum class.  The first argument of the C<import()> method is an
optional options HASH reference. The allowed options are:

=over 2

=item * C<class> (a non-empty string; available as of version 1.0.0)

An enum class can be build at runtime.  In this case The C<class> option
should be used to set the enum class name.

=item * C<counter> (a CODE reference; available as of version 1.1.0)

The C<counter> option can be used to overwrite the default ordinal number
generator. It should return a unique value for each enum object in the list.
The values should be numeric and comparable in pairs using the C<E<lt>=E<gt>>
operator.

=item * C<export> (a boolean value; available as of version 1.0.0)

If the C<export> option is set to true, the builder prepares enum constants
that are stored in the variable C<@EXPORT_OK> and it creates an C<:all>
tag that is part of the variable C<%EXPORT_TAGS>. Any separately loaded
exporter module like for example L<Exporter> enables the feature to export
enum constants.

=item * C<predicate> (a boolean value; available as of version 1.2.0)

If the C<predicate> option is set to true, the builder creates C<is_*()>
predicate methods (object methods) for each enum object in the list.

=item * C<prefix> (a non-empty string; available as of version 1.2.0)

The C<prefix> option can be used to specify a common prefix for the names of
the enum objects in the list.

=item * C<to_json> (a boolean value; available as of version 1.3.0)

If the C<to_json> option is set to true, the builder creates a C<TO_JSON()>
method (object method). This default implementation returns the name of the
calling enum object.

=back

The remaining arguments of the C<import()> method are the names of the
enum objects in the list. If the enum objects have custom attributes, an
additional attributes HASH reference is assigned to each name. If present
all enum objects in the list have to have the same attribute names.

C<Class::Enumration::Builder> is usually C<use>d in a separate module. In
this case the build process happens at compile time. The enum class name
equals the package name.

If you want to override the default stringification you have to pre-declare
the C<to_string()> before loading the builder.

=head1 AUTHOR

Sven Willenbuecher <sven.willenbuecher@gmx.de>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2025 by Sven Willenbuecher.

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
