NAME
    Perinci::Sub::Wrapper - A multi-purpose subroutine wrapping framework

VERSION
    version 0.30

SYNOPSIS
     use Perinci::Sub::Wrapper qw(wrap_sub);
     my $res = wrap_sub(sub => sub {die "test\n"}, meta=>{...});
     my ($wrapped, $meta) = ($res->[2]{sub}, $res->[2]{meta});
     $wrapped->(); # call the wrapped function

DESCRIPTION
    Perinci::Sub::Wrapper is an extensible subroutine wrapping framework. It
    works by creating a single "large" wrapper function from a composite
    bits of code, instead of using multiple small wrappers (a la Python's
    decorator). The single-wrapper approach has the benefit of smaller
    function call overhead. You can still wrap multiple times if needed.

    This module is used to enforce Rinci properties, e.g. "args" (by
    performing schema validation before calling the function), "timeout" (by
    doing function call inside an "eval()" and using "alarm()" to limit the
    execution), or "retry" (by wrapping function call inside a simple retry
    loop).

    It can also be used to convert argument passing style, e.g. from
    "args_as" "array" to "args_as" "hash", so you can call function using
    named arguments even though the function accepts positional arguments.

    There are many other possible uses.

    This module uses Log::Any for logging.

EXTENDING
    The framework is simple and extensible. Please delve directly into the
    source code for now. Some notes:

    The internal uses OO.

    The main wrapper building mechanism is in the "wrap()" method.

    For each Rinci property, it will call "handle_NAME()" wrapper handler
    method. The "handlemeta_NAME()" methods are called first, to determine
    order of processing. You can supply these methods either by subclassing
    the class or, more simply, monkeypatching the method in the
    "Perinci::Sub::Wrapper" package.

    The wrapper handler method will be called with a hash argument,
    containing these keys: value (property value), new (this key will exist
    if "convert" argument of "wrap()" exists, to convert a property to a new
    value).

    For properties that have name in the form of "NAME1.NAME2.NAME3" (i.e.,
    dotted) only the first part of the name will be used (i.e.,
    "handle_NAME1()").

METHODS
    The OO interface is only used internally or when you want to extend the
    wrapper.

FAQ
  caller() doesn't work from inside my wrapped code!
    Wrapping adds at least one or two levels of calls: one for the wrapper
    subroutine itself, the other is for the eval trap loop which can be
    disabled but is enabled by default. The 'goto-&NAME' special form, which
    can replace subroutine and avoid adding another call level, cannot be
    used because wrapping also needs to postprocess function result.

    This poses a problem if you need to call caller() from within your
    wrapped code; it will be off by at least one or two also.

SEE ALSO
    Perinci

DESCRIPTION
    This module has Rinci metadata.

FUNCTIONS
    None are exported by default, but they are exportable.

  caller(@args) -> bool
    Wrapper-aware caller().

    Just like Perl's builtin caller(), except that this one will ignore
    wrapper code in the call stack. You should use this if your code is
    potentially wrapped.

    Arguments ('*' denotes required arguments):

    *   n => *any*

    Return value:

  wrap_all_subs(%args) -> [status, msg, result, meta]
    Wrap all subroutines in a package and replace them with the wrapped
    version.

    This function will search all subroutines in a package which have
    metadata, wrap them, then replace the original subroutines and metadata
    with the wrapped version.

    One common use case is to put something like this at the bottom of your
    module:

        Perinci::Sub::Wrapper::wrap_all_subs();

    to wrap ("protect") all your module's subroutines and discard the
    original unwrapped version.

    Arguments ('*' denotes required arguments):

    *   package => *str*

        Package to search subroutines in.

        Default is caller package.

    *   wrap_args => *hash*

        Arguments to pass to wrap_sub().

        Each subroutine will be wrapped by wrap*sub(). This argument
        specifies what arguments to pass to wrap*sub().

        Note: If you need different arguments for different subroutine,
        perhaps this function is not for you. You can perform your own loop
        and wrap_sub().

    Return value:

    Returns an enveloped result (an array). First element (status) is an
    integer containing HTTP status code (200 means OK, 4xx caller error, 5xx
    function error). Second element (msg) is a string containing error
    message, or 'OK' if status is 200. Third element (result) is optional,
    the actual result. Fourth element (meta) is called result metadata and
    is optional, a hash that contains extra information.

  wrap_sub(%args) -> [status, msg, result, meta]
    Wrap subroutine to do various things, like enforcing Rinci properties.

    Will wrap subroutine and bless the generated wrapped subroutine (by
    default into 'Perinci::Sub::Wrapped') as a way of marking that the
    subroutine is a wrapped one.

    Arguments ('*' denotes required arguments):

    *   compile => *bool* (default: 1)

        Whether to compile the generated wrapper.

        Can be set to 0 to not actually wrap but just return the generated
        wrapper source code.

    *   convert => *hash*

        Properties to convert to new value.

        Not all properties can be converted, but these are a partial list of
        those that can: v (usually do not need to be specified when
        converting from 1.0 to 1.1, will be done automatically), args*as,
        result*naked, default_lang.

    *   debug => *bool* (default: 0)

        Generate code with debugging.

        If turned on, will produce various debugging in the generated code.
        Currently what this does:

        *   add more comments (e.g. for each property handler)

    *   forbid_tags => *array*

        Forbid properties which have certain wrapping tags.

        Some property wrapper, like dies*on*error (see
        Perinci::Sub::Property::dies*on*error) has tags 'die', to signify
        that it can cause wrapping code to die.

        Sometimes such properties are not desirable, e.g. in daemon
        environment. The use of such properties can be forbidden using this
        setting.

    *   meta* => *hash*

        The function metadata.

    *   normalize_schema => *bool* (default: 1)

        Whether to normalize schemas in metadata.

        By default, wrapper normalize Sah schemas in metadata, like in
        'args' or 'result' property, for convenience so that it does not
        need to be normalized again prior to use. If you want to turn off
        this behaviour, set to false.

    *   remove_internal_properties => *bool* (default: 1)

        Whether to remove properties prefixed with _.

        By default, wrapper removes internal properties (properties which
        start with underscore) in the new metadata. Set this to false to
        keep them.

    *   sub* => *code*

        The code to wrap.

    *   sub_name => *str*

        The name of the code, e.g. Foo::func.

        It is a good idea to supply this so that wrapper code can display
        this information when they need to (e.g. see
        Perinci::Sub::Property::dies*on*error).

    *   trap => *bool* (default: 1)

        Whether to trap exception using an eval block.

        If set to true, will wrap call using an eval {} block and return 500
        /undef if function dies. Note that if some other properties requires
        an eval block (like 'timeout') an eval block will be added
        regardless of this parameter.

    Return value:

    Returns an enveloped result (an array). First element (status) is an
    integer containing HTTP status code (200 means OK, 4xx caller error, 5xx
    function error). Second element (msg) is a string containing error
    message, or 'OK' if status is 200. Third element (result) is optional,
    the actual result. Fourth element (meta) is called result metadata and
    is optional, a hash that contains extra information.

  wrapped() -> bool
    Check whether we are wrapped.

    This function is to be run inside a subroutine to check if *that*
    subroutine is wrapped by Perinci::Sub::Wrapper. For example:

        sub some_sub {
            print "I'm wrapped" if wrapped();
        }

    See also this package's caller(), a wrapper-aware replacement for Perl's
    builtin caller().

    No arguments.

    Return value:

AUTHOR
    Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2012 by Steven Haryanto.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

CHANGES
  Version 0.30 (2012-08-09)
    *   [INCOMPATIBLE CHANGES] Now looks for property handler in
        Perinci::Sub::Property::* instead of Perinci::Sub::property::* (fix
        casing).

  Version 0.29 (2012-08-08)
    *   Add caller() function.

  Version 0.28 (2012-08-04)
    *   Add wrapped() function.

  Version 0.27 (2012-08-02)
    *   No functional changes. Update to new Perinci::Role::MetaAccessor

    *   interface (0.26).

  Version 0.26 (2012-08-01)
    *   [ENHANCEMENTS] Add wrap_all_subs().

  Version 0.25 (2012-07-31)
    *   [ENHANCEMENTS] Add argument: sub_name (also so that 'dies_on_error'
        property can display proper die message showing subroutine name).

    *   [ENHANCEMENTS] Add argument: forbid_tags.

    *   [FIXES] Change handling of 'result_naked' property so that
        'dies_on_error' property can get result status + message properly.

  Version 0.24 (2012-07-31)
    *   [ENHANCEMENTS] Introduce section: 'before_return_res'.

    *   [INCOMPATIBLE CHANGES] Introduce protocol version which must be
        specified by all property handlers (assumed to be 1 if unspecified).
        This is bumped whenever an incompatible change at the basic
        structure of wrapper code is introduced. Bumping the protocol
        version will force all existing property handlers to be updated.

    *   [INCOMPATIBLE CHANGES] Bump protocol version from 1 to 2: to return
        result immediately, handler must now say 'goto RETURN_RES' instead
        of 'return $res' directly. This is so that some handlers get the
        last chance to do something to $res before it is returned.

  Version 0.23 (2012-07-29)
    *   [ENHANCEMENTS] When encountering an unknown property, automatically
        try to require Perinci::Sub::property::PROP first. So you don't have
        to manually use() the property modules.

    *   [ENHANCEMENTS] Add wrap_sub() argument 'debug' to show debugging in
        generated code. Currently show the handler from which each line
        comes from.

    *   [ENHANCEMENTS] Check known arg spec key.

  Version 0.22 (2012-06-21)
    *   features: Require transaction ('-tx_manager' argument) if
        features->{tx}{req} is 1.

  Version 0.21 (2012-06-07)
    *   [FIXES] deps: '-undo_trash_dir' argument is not needed when
        '-tx_manager' argument is given.

  Version 0.20 (2012-06-07)
    *   Update to Rinci 1.1.18 (some new deps introduced: 'tmp_dir',

    *   'trash_dir', 'undo_trash_dir'; some removed: 'undo_storage').

  Version 0.19 (2012-03-22)
    *   [ENHANCEMENTS] 'default_lang' also converts language properties in
        tag metadata in 'tags'.

  Version 0.18 (2012-03-21)
    *   No functional changes. Rebuild with Perinci PodWeaver plugin
        enabled.

  Version 0.17 (2012-03-21)
    *   [ENHANCEMENTS] Convert 'default_lang' property.

    *   [ENHANCEMENTS] 'remove_internal_properties' now also removes
        internal properties in 'result', 'examples', and 'links'.

  Version 0.16 (2012-03-16)
    *   [ENHANCEMENTS] Convert 1.0 - 1.1: Set argument spec's summary from
        argument schema.

  Version 0.15 (2012-02-28)
    *   [NEW FEATURES] Handle 'cmdline_aliases' (Rinci 1.1.8+)

    *   [NEW FEATURES] Convert 1.0 'arg_aliases' to 'cmdline_aliases'

    *   [NEW FEATURES] Add 'remove_internal_properties' wrap option.

  Version 0.14 (2012-02-23)
    *   [NEW FEATURES] Automatically convert metadata v1.0 to v1.1. Finally
        all the old Sub::Spec specs are now usable again.

  Version 0.13 (2012-02-22)
    *   [NEW FEATURES] Sah schemas in 'args' and 'result' are now normalized
        in the new metadata, this is to make it simpler for other code to
        use the schema (e.g. Perinci-Access when completing args). New
        metadata is now a deep clone of the old (instead of just a shallow
        copy), this might increase memory usage.

  Version 0.12 (2012-02-15)
    *   [REMOVED FEATURES] Remove 'force' argument. wrap_sub() still mark
        wrapping by blessing the generated wrapper, but will gladly double
        wrap. I believe caching should be done in the upper layers.

  Version 0.11 (2012-02-13)
    *   [ETC] Add tweak to work better with 'retry' property wrapper.

  Version 0.10 (2012-02-13)
    *   [NEW FEATURES] Add wrap option 'compile'.

  Version 0.09 (2012-02-13)
    *   [BUG FIXES] Fix indenting in generated code.

  Version 0.08 (2012-02-12)
    *   [BUG FIXES] Convert keys are now respected even though meta does not
        have that key.

  Version 0.07 (2012-02-12)
    *   Add (or re-enable) unshift_lines()

    *   Extract test routine to Test::Perinci::Sub::Wrapper to make it
        usable from other Perinci-Sub-property-* distributions.

  Version 0.06 (2012-02-12)
    *   Rename distribution from Sub-Spec-Wrapper to Perinci-Sub-Wrapper.

  Version 0.05 (2012-01-21)
    *   No functional changes. Mark Sub-Spec-Wrapper deprecated.

  Version 0.04 (2011-10-19)
    *   No functional changes. Add missing dependency to

    *   Sub::Spec::ConvertArgs::Array [thanks cpant & Andreas].

  Version 0.03 (2011-09-22)
    *   [ENHANCEMENTS] Support 'args_as' spec clause
        (hash/hashref/array/arrayref supported, but object not yet).

  Version 0.02 (2011-08-31)
    *   Build and POD fixes.

  Version 0.01 (2011-08-31)
    *   First release.

