1 package HTML::Zoom::FilterStream;
4 use warnings FATAL => 'all';
7 my ($class, $args) = @_;
10 _stream => $args->{stream},
11 _match => $args->{match},
12 _filter => $args->{filter},
21 # if our main stream is already gone then we can short-circuit
22 # straight out - there's no way for an alternate stream to be there
24 return unless $self->{_stream};
26 # if we have an alternate stream (provided by a filter call resulting
27 # from a match on the main stream) then we want to read from that until
28 # it's gone - we're still effectively "in the match" but this is the
29 # point at which that fact is abstracted away from downstream consumers
31 if (my $alt = $self->{_alt_stream}) {
33 if (my ($evt) = $alt->next) {
37 # once the alternate stream is exhausted we can throw it away so future
38 # requests fall straight through to the main stream
40 delete $self->{_alt_stream};
43 # if there's no alternate stream currently, process the main stream
45 while (my ($evt) = $self->{_stream}->next) {
47 # don't match this event? return it immediately
49 return $evt unless $evt->{type} eq 'OPEN' and $self->{_match}->($evt);
51 # run our filter routine against the current event
53 my ($res) = $self->{_filter}->($evt, $self->{_stream});
55 # if the result is just an event, we can return that now
57 return $res if ref($res) eq 'HASH';
59 # if no result at all, jump back to the top of the loop to get the
60 # next event and try again - the filter has eaten this one
62 next unless defined $res;
64 # ARRAY means a pair of [ $evt, $new_stream ]
66 if (ref($res) eq 'ARRAY') {
67 $self->{_alt_stream} = $res->[1];
71 # the filter returned a stream - if it contains something return the
72 # first entry and stash it as the new alternate stream
74 if (my ($new_evt) = $res->next) {
75 $self->{_alt_stream} = $res;
79 # we got a new alternate stream but it turned out to be empty
80 # - this will happens for e.g. with an in place close (<foo />) that's
81 # being removed. In that case, we fall off to loop back round and try
82 # the next event from our main stream
85 # main stream exhausted so throw it away so we hit the short circuit
86 # at the top and return nothing to indicate to our caller we're done
88 delete $self->{_stream};