=head1 NAME

UniEvent::Streamer::Output - base class for custom consumers for streamer



=head1 SYNOPSYS

    package MyOutput;
    use parent 'UniEvent::Streamer::Output';
    use 5.012;
    
    sub new {
        my ($class, ...) = @_;
        my $self = $class->SUPER::new();
        ...
        return $self;
    }
    
    sub start            { ... }
    sub stop             { ... }
    sub write            { ... }
    sub write_queue_size { return length(shift->{buffer}) }

    ...
    
    my $output = MyOutput->new(...);
    my $streamer = UE::Streamer->new($input, $output);
    ...



=head1 DESCRIPTION

This is base class for custom output streams, meant to be assigned with L<UniEvent::Streamer>.
It is assumed, that you will send data, given by L<UniEvent::Streamer>, to some external destination will generate data and eof event, and

C<Streamer> will use output object as follows: it will call C<start()> once and then will periodically call C<write()>. You are expected to write that data somewhere
and call C<handle_write()> for each corresponding C<write()>. In case of any error you must call C<handle_write()> with error.
You must implement any kind of dynamic-size buffer (if it's not already implemented by lower level objects that you use to write data) and return summary size
of all not yet completed writes from method C<write_queue_size()> which will be called by C<Streamer> periodically.
C<Streamer> will call C<stop()> method once when the process finishes successfully or with error.



=head1 METHODS

=head2 new()

Constructs new output stream.

If you override this method, you MUST proxy to parent and use return value as C<$self>.


=head2 start($loop)

This method will be invoked by C<Streamer> upon start. Executed once per object lifetime.

This method should return C<undef> if no error occured or L<XS::ErrorCode> object otherwise.

NOTE: This is a callback, do not call this method by yourself!


=head2 stop()

This method is invoked when C<Streamer> finishes. Executed once per object lifetime. No any further I/O is expected.

In this method you are expected to release all resources.

NOTE: This is a callback, do not call this method by yourself!


=head2 write($data)

This method is invoked when C<Streamer> receives chunk of data from input.

You are expected to start writing process for that chunk. When the process finishes you must call C<handle_write()>. C<Streamer> may call C<write()> many times
without waiting for you to call C<handle_write()> for previous requests.
Regardless of how calls to C<write()> were made you must call C<handle_write()> for each C<write()> when appropriate write request finishes.

This method should return C<undef> if no error occured or L<XS::ErrorCode> object otherwise. If an error occurs later, in async writing process, call
C<handle_write()> with error. Anyway, regardless of how you return error (in this method or with C<handle_write()>), after that the process will stop immediately
and C<stop()> will be called. You should not call C<handle_write()> after that.

NOTE: This is a callback, do not call this method by yourself!


=head2 write_queue_size()

This method must return size of data buffered in memory in your output object or in lower-level objects.

If this size will be greater than configured max buffer size in C<Streamer>, it will temporarily suspend input stream, giving you time to complete a part of
pending writes.

You must implement such buffer by yourself. The reason why this buffer is not implemented in C<Streamer> itself is that many objects already have output buffer.
For example L<UniEvent::Stream> handles have output buffer and C<write_queue_size()> method. In this case implementing such buffer in C<Streamer> would lead
to less efficient execution.

NOTE: This is a callback, do not call this method by yourself!


=head2 handle_write([$error])

You must call this method when one of pending write requests finishes. If any error occured during sending data, pass C<$error> argument.

C<$error> must be L<XS::ErrorCode> object. You can use UniEvent::SystemError::* constants to create errors.

    $self->handle_write(UniEvent::SystemError::timed_out);

=cut
