All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.reactivex.flowable.internal.operators.FlowableFromIterable Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2016-present, RxJava Contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
 * the License for the specific language governing permissions and limitations under the License.
 */

package io.reactivex.flowable.internal.operators;

import java.util.Iterator;

import org.reactivestreams.Subscriber;

import hu.akarnokd.reactivestreams.extensions.ConditionalSubscriber;
import io.reactivex.common.annotations.Nullable;
import io.reactivex.common.exceptions.Exceptions;
import io.reactivex.common.internal.functions.ObjectHelper;
import io.reactivex.flowable.Flowable;
import io.reactivex.flowable.internal.subscriptions.*;
import io.reactivex.flowable.internal.utils.BackpressureHelper;

public final class FlowableFromIterable extends Flowable {

    final Iterable source;

    public FlowableFromIterable(Iterable source) {
        this.source = source;
    }

    @Override
    public void subscribeActual(Subscriber s) {
        Iterator it;
        try {
            it = source.iterator();
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            EmptySubscription.error(e, s);
            return;
        }

        subscribe(s, it);
    }

    public static  void subscribe(Subscriber s, Iterator it) {
        boolean hasNext;
        try {
            hasNext = it.hasNext();
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            EmptySubscription.error(e, s);
            return;
        }

        if (!hasNext) {
            EmptySubscription.complete(s);
            return;
        }

        if (s instanceof ConditionalSubscriber) {
            s.onSubscribe(new IteratorConditionalSubscription(
                    (ConditionalSubscriber)s, it));
        } else {
            s.onSubscribe(new IteratorSubscription(s, it));
        }
    }

    abstract static class BaseRangeSubscription extends BasicFusedQueueSubscription {
        private static final long serialVersionUID = -2252972430506210021L;

        Iterator it;

        volatile boolean cancelled;

        boolean once;

        BaseRangeSubscription(Iterator it) {
            this.it = it;
        }

        @Override
        public final int requestFusion(int mode) {
            return mode & SYNC;
        }

        @Nullable
        @Override
        public final T poll() {
            if (it == null) {
                return null;
            }
            if (!once) {
                once = true;
            } else {
                if (!it.hasNext()) {
                    return null;
                }
            }
            return ObjectHelper.requireNonNull(it.next(), "Iterator.next() returned a null value");
        }


        @Override
        public final boolean isEmpty() {
            return it == null || !it.hasNext();
        }

        @Override
        public final void clear() {
            it = null;
        }

        @Override
        public final void request(long n) {
            if (SubscriptionHelper.validate(n)) {
                if (BackpressureHelper.add(this, n) == 0L) {
                    if (n == Long.MAX_VALUE) {
                        fastPath();
                    } else {
                        slowPath(n);
                    }
                }
            }
        }


        @Override
        public final void cancel() {
            cancelled = true;
        }

        abstract void fastPath();

        abstract void slowPath(long r);
    }

    static final class IteratorSubscription extends BaseRangeSubscription {


        private static final long serialVersionUID = -6022804456014692607L;

        final Subscriber actual;

        IteratorSubscription(Subscriber actual, Iterator it) {
            super(it);
            this.actual = actual;
        }

        @Override
        void fastPath() {
            Iterator it = this.it;
            Subscriber a = actual;
            for (;;) {
                if (cancelled) {
                    return;
                }

                T t;

                try {
                    t = it.next();
                } catch (Throwable ex) {
                    Exceptions.throwIfFatal(ex);
                    a.onError(ex);
                    return;
                }

                if (cancelled) {
                    return;
                }

                if (t == null) {
                    a.onError(new NullPointerException("Iterator.next() returned a null value"));
                    return;
                } else {
                    a.onNext(t);
                }

                if (cancelled) {
                    return;
                }

                boolean b;

                try {
                    b = it.hasNext();
                } catch (Throwable ex) {
                    Exceptions.throwIfFatal(ex);
                    a.onError(ex);
                    return;
                }


                if (!b) {
                    if (!cancelled) {
                        a.onComplete();
                    }
                    return;
                }
            }
        }

        @Override
        void slowPath(long r) {
            long e = 0L;
            Iterator it = this.it;
            Subscriber a = actual;

            for (;;) {

                while (e != r) {

                    if (cancelled) {
                        return;
                    }

                    T t;

                    try {
                        t = it.next();
                    } catch (Throwable ex) {
                        Exceptions.throwIfFatal(ex);
                        a.onError(ex);
                        return;
                    }

                    if (cancelled) {
                        return;
                    }

                    if (t == null) {
                        a.onError(new NullPointerException("Iterator.next() returned a null value"));
                        return;
                    } else {
                        a.onNext(t);
                    }

                    if (cancelled) {
                        return;
                    }

                    boolean b;

                    try {
                        b = it.hasNext();
                    } catch (Throwable ex) {
                        Exceptions.throwIfFatal(ex);
                        a.onError(ex);
                        return;
                    }

                    if (!b) {
                        if (!cancelled) {
                            a.onComplete();
                        }
                        return;
                    }

                    e++;
                }

                r = get();
                if (e == r) {
                    r = addAndGet(-e);
                    if (r == 0L) {
                        return;
                    }
                    e = 0L;
                }
            }
        }

    }

    static final class IteratorConditionalSubscription extends BaseRangeSubscription {


        private static final long serialVersionUID = -6022804456014692607L;

        final ConditionalSubscriber actual;

        IteratorConditionalSubscription(ConditionalSubscriber actual, Iterator it) {
            super(it);
            this.actual = actual;
        }

        @Override
        void fastPath() {
            Iterator it = this.it;
            ConditionalSubscriber a = actual;
            for (;;) {
                if (cancelled) {
                    return;
                }

                T t;

                try {
                    t = it.next();
                } catch (Throwable ex) {
                    Exceptions.throwIfFatal(ex);
                    a.onError(ex);
                    return;
                }

                if (cancelled) {
                    return;
                }

                if (t == null) {
                    a.onError(new NullPointerException("Iterator.next() returned a null value"));
                    return;
                } else {
                    a.tryOnNext(t);
                }

                if (cancelled) {
                    return;
                }

                boolean b;

                try {
                    b = it.hasNext();
                } catch (Throwable ex) {
                    Exceptions.throwIfFatal(ex);
                    a.onError(ex);
                    return;
                }

                if (!b) {
                    if (!cancelled) {
                        a.onComplete();
                    }
                    return;
                }
            }
        }

        @Override
        void slowPath(long r) {
            long e = 0L;
            Iterator it = this.it;
            ConditionalSubscriber a = actual;

            for (;;) {

                while (e != r) {

                    if (cancelled) {
                        return;
                    }

                    T t;

                    try {
                        t = it.next();
                    } catch (Throwable ex) {
                        Exceptions.throwIfFatal(ex);
                        a.onError(ex);
                        return;
                    }

                    if (cancelled) {
                        return;
                    }

                    boolean b;
                    if (t == null) {
                        a.onError(new NullPointerException("Iterator.next() returned a null value"));
                        return;
                    } else {
                        b = a.tryOnNext(t);
                    }

                    if (cancelled) {
                        return;
                    }

                    boolean hasNext;

                    try {
                        hasNext = it.hasNext();
                    } catch (Throwable ex) {
                        Exceptions.throwIfFatal(ex);
                        a.onError(ex);
                        return;
                    }

                    if (!hasNext) {
                        if (!cancelled) {
                            a.onComplete();
                        }
                        return;
                    }

                    if (b) {
                        e++;
                    }
                }

                r = get();
                if (e == r) {
                    r = addAndGet(-e);
                    if (r == 0L) {
                        return;
                    }
                    e = 0L;
                }
            }
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy