/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.util.stream;

import org.testng.annotations.Test;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Spliterator;
import java.util.function.*;

import static org.testng.Assert.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;

/**
 * Assertion methods for spliterators, to be called from other tests
 */
public class SpliteratorTestHelper {

    public interface ContentAsserter<T> {
        void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered);
    }

    private static ContentAsserter<Object> DEFAULT_CONTENT_ASSERTER
            = SpliteratorTestHelper::assertContents;

    @SuppressWarnings("unchecked")
    private static <T> ContentAsserter<T> defaultContentAsserter() {
        return (ContentAsserter<T>) DEFAULT_CONTENT_ASSERTER;
    }

    public static void testSpliterator(Supplier<Spliterator<Integer>> supplier) {
        testSpliterator(supplier, defaultContentAsserter());
    }

    public static void testSpliterator(Supplier<Spliterator<Integer>> supplier,
                                       ContentAsserter<Integer> asserter) {
        testSpliterator(supplier, (Consumer<Integer> b) -> b, asserter);
    }

    public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier) {
        testIntSpliterator(supplier, defaultContentAsserter());
    }

    public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier,
                                          ContentAsserter<Integer> asserter) {
        class BoxingAdapter implements Consumer<Integer>, IntConsumer {
            private final Consumer<Integer> b;

            BoxingAdapter(Consumer<Integer> b) {
                this.b = b;
            }

            @Override
            public void accept(Integer value) {
                throw new IllegalStateException();
            }

            @Override
            public void accept(int value) {
                b.accept(value);
            }
        }

        testSpliterator(supplier, BoxingAdapter::new, asserter);
    }

    public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier) {
        testLongSpliterator(supplier, defaultContentAsserter());
    }

    public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier,
                                           ContentAsserter<Long> asserter) {
        class BoxingAdapter implements Consumer<Long>, LongConsumer {
            private final Consumer<Long> b;

            BoxingAdapter(Consumer<Long> b) {
                this.b = b;
            }

            @Override
            public void accept(Long value) {
                throw new IllegalStateException();
            }

            @Override
            public void accept(long value) {
                b.accept(value);
            }
        }

        testSpliterator(supplier, BoxingAdapter::new, asserter);
    }

    public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier) {
        testDoubleSpliterator(supplier, defaultContentAsserter());
    }

    public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier,
                                             ContentAsserter<Double> asserter) {
        class BoxingAdapter implements Consumer<Double>, DoubleConsumer {
            private final Consumer<Double> b;

            BoxingAdapter(Consumer<Double> b) {
                this.b = b;
            }

            @Override
            public void accept(Double value) {
                throw new IllegalStateException();
            }

            @Override
            public void accept(double value) {
                b.accept(value);
            }
        }

        testSpliterator(supplier, BoxingAdapter::new, asserter);
    }

    static <T, S extends Spliterator<T>> void testSpliterator(Supplier<S> supplier,
                                                              UnaryOperator<Consumer<T>> boxingAdapter,
                                                              ContentAsserter<T> asserter) {
        ArrayList<T> fromForEach = new ArrayList<>();
        Spliterator<T> spliterator = supplier.get();
        Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add);
        spliterator.forEachRemaining(addToFromForEach);

        Collection<T> exp = Collections.unmodifiableList(fromForEach);

        testNullPointerException(supplier);
        testForEach(exp, supplier, boxingAdapter, asserter);
        testTryAdvance(exp, supplier, boxingAdapter, asserter);
        testMixedTryAdvanceForEach(exp, supplier, boxingAdapter, asserter);
        testMixedTraverseAndSplit(exp, supplier, boxingAdapter, asserter);
        testSplitAfterFullTraversal(supplier, boxingAdapter);
        testSplitOnce(exp, supplier, boxingAdapter, asserter);
        testSplitSixDeep(exp, supplier, boxingAdapter, asserter);
        testSplitUntilNull(exp, supplier, boxingAdapter, asserter);
    }

    //

    private static <T, S extends Spliterator<T>> void testNullPointerException(Supplier<S> s) {
        S sp = s.get();
        // Have to check instances and use casts to avoid tripwire messages and
        // directly test the primitive methods
        if (sp instanceof Spliterator.OfInt) {
            Spliterator.OfInt psp = (Spliterator.OfInt) sp;
            executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((IntConsumer) null));
            executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((IntConsumer) null));
        }
        else if (sp instanceof Spliterator.OfLong) {
            Spliterator.OfLong psp = (Spliterator.OfLong) sp;
            executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((LongConsumer) null));
            executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((LongConsumer) null));
        }
        else if (sp instanceof Spliterator.OfDouble) {
            Spliterator.OfDouble psp = (Spliterator.OfDouble) sp;
            executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((DoubleConsumer) null));
            executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((DoubleConsumer) null));
        }
        else {
            executeAndCatch(NullPointerException.class, () -> sp.forEachRemaining(null));
            executeAndCatch(NullPointerException.class, () -> sp.tryAdvance(null));
        }
    }

    private static <T, S extends Spliterator<T>> void testForEach(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        ArrayList<T> fromForEach = new ArrayList<>();
        spliterator = supplier.get();
        Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add);
        spliterator.forEachRemaining(addToFromForEach);

        // Assert that forEach now produces no elements
        spliterator.forEachRemaining(boxingAdapter.apply(
                e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));
        // Assert that tryAdvance now produce no elements
        spliterator.tryAdvance(boxingAdapter.apply(
                e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

        // assert that size, tryAdvance, and forEach are consistent
        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, exp.size());
        }
        assertEquals(fromForEach.size(), exp.size());

        asserter.assertContents(fromForEach, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testTryAdvance(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        spliterator = supplier.get();
        ArrayList<T> fromTryAdvance = new ArrayList<>();
        Consumer<T> addToFromTryAdvance = boxingAdapter.apply(fromTryAdvance::add);
        while (spliterator.tryAdvance(addToFromTryAdvance)) { }

        // Assert that forEach now produces no elements
        spliterator.forEachRemaining(boxingAdapter.apply(
                e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));
        // Assert that tryAdvance now produce no elements
        spliterator.tryAdvance(boxingAdapter.apply(
                e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

        // assert that size, tryAdvance, and forEach are consistent
        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, exp.size());
        }
        assertEquals(fromTryAdvance.size(), exp.size());

        asserter.assertContents(fromTryAdvance, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testMixedTryAdvanceForEach(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        // tryAdvance first few elements, then forEach rest
        ArrayList<T> dest = new ArrayList<>();
        spliterator = supplier.get();
        Consumer<T> addToDest = boxingAdapter.apply(dest::add);
        for (int i = 0; i < 10 && spliterator.tryAdvance(addToDest); i++) { }
        spliterator.forEachRemaining(addToDest);

        // Assert that forEach now produces no elements
        spliterator.forEachRemaining(boxingAdapter.apply(
                e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));
        // Assert that tryAdvance now produce no elements
        spliterator.tryAdvance(boxingAdapter.apply(
                e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, dest.size());
        }
        assertEquals(dest.size(), exp.size());

        asserter.assertContents(dest, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        // tryAdvance first few elements, then forEach rest
        ArrayList<T> dest = new ArrayList<>();
        spliterator = supplier.get();
        Consumer<T> b = boxingAdapter.apply(dest::add);

        Spliterator<T> spl1, spl2, spl3;
        spliterator.tryAdvance(b);
        spl2 = spliterator.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        spliterator.tryAdvance(b);
        spl3 = spliterator.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        spliterator.tryAdvance(b);
        spliterator.forEachRemaining(b);

        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, dest.size());
        }
        assertEquals(dest.size(), exp.size());

        asserter.assertContents(dest, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testSplitAfterFullTraversal(
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter) {
        // Full traversal using tryAdvance
        Spliterator<T> spliterator = supplier.get();
        while (spliterator.tryAdvance(boxingAdapter.apply(e -> { }))) { }
        Spliterator<T> split = spliterator.trySplit();
        assertNull(split);

        // Full traversal using forEach
        spliterator = supplier.get();
        spliterator.forEachRemaining(boxingAdapter.apply(e -> { }));
        split = spliterator.trySplit();
        assertNull(split);

        // Full traversal using tryAdvance then forEach
        spliterator = supplier.get();
        spliterator.tryAdvance(boxingAdapter.apply(e -> { }));
        spliterator.forEachRemaining(boxingAdapter.apply(e -> { }));
        split = spliterator.trySplit();
        assertNull(split);
    }

    private static <T, S extends Spliterator<T>> void testSplitOnce(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        long sizeIfKnown = spliterator.getExactSizeIfKnown();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        ArrayList<T> fromSplit = new ArrayList<>();
        Spliterator<T> s1 = supplier.get();
        Spliterator<T> s2 = s1.trySplit();
        long s1Size = s1.getExactSizeIfKnown();
        long s2Size = (s2 != null) ? s2.getExactSizeIfKnown() : 0;
        Consumer<T> addToFromSplit = boxingAdapter.apply(fromSplit::add);
        if (s2 != null)
            s2.forEachRemaining(addToFromSplit);
        s1.forEachRemaining(addToFromSplit);

        if (sizeIfKnown >= 0) {
            assertEquals(sizeIfKnown, fromSplit.size());
            if (s1Size >= 0 && s2Size >= 0)
                assertEquals(sizeIfKnown, s1Size + s2Size);
        }

        asserter.assertContents(fromSplit, exp, isOrdered);
    }

    private static <T, S extends Spliterator<T>> void testSplitSixDeep(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        S spliterator = supplier.get();
        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);

        for (int depth=0; depth < 6; depth++) {
            List<T> dest = new ArrayList<>();
            spliterator = supplier.get();

            assertSpliterator(spliterator);

            // verify splitting with forEach
            splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false);
            asserter.assertContents(dest, exp, isOrdered);

            // verify splitting with tryAdvance
            dest.clear();
            spliterator = supplier.get();
            splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), true);
            asserter.assertContents(dest, exp, isOrdered);
        }
    }

    private static <T, S extends Spliterator<T>>
    void splitSixDeepVisitor(int depth, int curLevel,
                             List<T> dest, S spliterator, UnaryOperator<Consumer<T>> boxingAdapter,
                             int rootCharacteristics, boolean useTryAdvance) {
        if (curLevel < depth) {
            long beforeSize = spliterator.getExactSizeIfKnown();
            Spliterator<T> split = spliterator.trySplit();
            if (split != null) {
                assertSpliterator(split, rootCharacteristics);
                assertSpliterator(spliterator, rootCharacteristics);

                if ((rootCharacteristics & Spliterator.SUBSIZED) != 0 &&
                    (rootCharacteristics & Spliterator.SIZED) != 0) {
                    assertEquals(beforeSize, split.estimateSize() + spliterator.estimateSize());
                }
                splitSixDeepVisitor(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance);
            }
            splitSixDeepVisitor(depth, curLevel + 1, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance);
        }
        else {
            long sizeIfKnown = spliterator.getExactSizeIfKnown();
            if (useTryAdvance) {
                Consumer<T> addToDest = boxingAdapter.apply(dest::add);
                int count = 0;
                while (spliterator.tryAdvance(addToDest)) {
                    ++count;
                }

                if (sizeIfKnown >= 0)
                    assertEquals(sizeIfKnown, count);

                // Assert that forEach now produces no elements
                spliterator.forEachRemaining(boxingAdapter.apply(
                        e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e)));

                Spliterator<T> split = spliterator.trySplit();
                assertNull(split);
            }
            else {
                List<T> leafDest = new ArrayList<>();
                Consumer<T> addToLeafDest = boxingAdapter.apply(leafDest::add);
                spliterator.forEachRemaining(addToLeafDest);

                if (sizeIfKnown >= 0)
                    assertEquals(sizeIfKnown, leafDest.size());

                // Assert that forEach now produces no elements
                spliterator.tryAdvance(boxingAdapter.apply(
                        e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e)));

                Spliterator<T> split = spliterator.trySplit();
                assertNull(split);

                dest.addAll(leafDest);
            }
        }
    }

    private static <T, S extends Spliterator<T>> void testSplitUntilNull(
            Collection<T> exp,
            Supplier<S> supplier,
            UnaryOperator<Consumer<T>> boxingAdapter,
            ContentAsserter<T> asserter) {
        Spliterator<T> s = supplier.get();
        boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED);
        assertSpliterator(s);

        List<T> splits = new ArrayList<>();
        Consumer<T> c = boxingAdapter.apply(splits::add);

        testSplitUntilNull(new SplitNode<T>(c, s));
        asserter.assertContents(splits, exp, isOrdered);
    }

    private static class SplitNode<T> {
        // Constant for every node
        final Consumer<T> c;
        final int rootCharacteristics;

        final Spliterator<T> s;

        SplitNode(Consumer<T> c, Spliterator<T> s) {
            this(c, s.characteristics(), s);
        }

        private SplitNode(Consumer<T> c, int rootCharacteristics, Spliterator<T> s) {
            this.c = c;
            this.rootCharacteristics = rootCharacteristics;
            this.s = s;
        }

        SplitNode<T> fromSplit(Spliterator<T> split) {
            return new SplitNode<>(c, rootCharacteristics, split);
        }
    }

    /**
     * Set the maximum stack capacity to 0.25MB. This should be more than enough to detect a bad spliterator
     * while not unduly disrupting test infrastructure given the test data sizes that are used are small.
     * Note that j.u.c.ForkJoinPool sets the max queue size to 64M (1 << 26).
     */
    private static final int MAXIMUM_STACK_CAPACITY = 1 << 18; // 0.25MB

    private static <T> void testSplitUntilNull(SplitNode<T> e) {
        // Use an explicit stack to avoid a StackOverflowException when testing a Spliterator
        // that when repeatedly split produces a right-balanced (and maybe degenerate) tree, or
        // for a spliterator that is badly behaved.
        Deque<SplitNode<T>> stack = new ArrayDeque<>();
        stack.push(e);

        int iteration = 0;
        while (!stack.isEmpty()) {
            assertTrue(iteration++ < MAXIMUM_STACK_CAPACITY, "Exceeded maximum stack modification count of 1 << 18");

            e = stack.pop();
            Spliterator<T> parentAndRightSplit = e.s;

            long parentEstimateSize = parentAndRightSplit.estimateSize();
            assertTrue(parentEstimateSize >= 0,
                       String.format("Split size estimate %d < 0", parentEstimateSize));

            long parentSize = parentAndRightSplit.getExactSizeIfKnown();
            Spliterator<T> leftSplit = parentAndRightSplit.trySplit();
            if (leftSplit == null) {
                parentAndRightSplit.forEachRemaining(e.c);
                continue;
            }

            assertSpliterator(leftSplit, e.rootCharacteristics);
            assertSpliterator(parentAndRightSplit, e.rootCharacteristics);

            if (parentEstimateSize != Long.MAX_VALUE && leftSplit.estimateSize() > 0
                && parentAndRightSplit.estimateSize() > 0) {
                assertTrue(leftSplit.estimateSize() < parentEstimateSize,
                           String.format("Left split size estimate %d >= parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
                assertTrue(parentAndRightSplit.estimateSize() < parentEstimateSize,
                           String.format("Right split size estimate %d >= parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
            }
            else {
                assertTrue(leftSplit.estimateSize() <= parentEstimateSize,
                           String.format("Left split size estimate %d > parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
                assertTrue(parentAndRightSplit.estimateSize() <= parentEstimateSize,
                           String.format("Right split size estimate %d > parent split size estimate %d",
                                         leftSplit.estimateSize(), parentEstimateSize));
            }

            long leftSize = leftSplit.getExactSizeIfKnown();
            long rightSize = parentAndRightSplit.getExactSizeIfKnown();
            if (parentSize >= 0 && leftSize >= 0 && rightSize >= 0)
                assertEquals(parentSize, leftSize + rightSize,
                             String.format("exact left split size %d + exact right split size %d != parent exact split size %d",
                                           leftSize, rightSize, parentSize));

            // Add right side to stack first so left side is popped off first
            stack.push(e.fromSplit(parentAndRightSplit));
            stack.push(e.fromSplit(leftSplit));
        }
    }

    private static void assertSpliterator(Spliterator<?> s, int rootCharacteristics) {
        if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) {
            assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED),
                       "Child split is not SUBSIZED when root split is SUBSIZED");
        }
        assertSpliterator(s);
    }

    private static void assertSpliterator(Spliterator<?> s) {
        if (s.hasCharacteristics(Spliterator.SUBSIZED)) {
            assertTrue(s.hasCharacteristics(Spliterator.SIZED));
        }
        if (s.hasCharacteristics(Spliterator.SIZED)) {
            assertTrue(s.estimateSize() != Long.MAX_VALUE);
            assertTrue(s.getExactSizeIfKnown() >= 0);
        }
        try {
            s.getComparator();
            assertTrue(s.hasCharacteristics(Spliterator.SORTED));
        } catch (IllegalStateException e) {
            assertFalse(s.hasCharacteristics(Spliterator.SORTED));
        }
    }

    private static<T> void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered) {
        if (isOrdered) {
            assertEquals(actual, expected);
        }
        else {
            LambdaTestHelpers.assertContentsUnordered(actual, expected);
        }
    }

    private static void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
        Exception caught = null;
        try {
            r.run();
        }
        catch (Exception e) {
            caught = e;
        }

        assertNotNull(caught,
                      String.format("No Exception was thrown, expected an Exception of %s to be thrown",
                                    expected.getName()));
        assertTrue(expected.isInstance(caught),
                   String.format("Exception thrown %s not an instance of %s",
                                 caught.getClass().getName(), expected.getName()));
    }

    static<U> void mixedTraverseAndSplit(Consumer<U> b, Spliterator<U> splTop) {
        Spliterator<U> spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }

    static void mixedTraverseAndSplit(IntConsumer b, Spliterator.OfInt splTop) {
        Spliterator.OfInt spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }
    static void mixedTraverseAndSplit(LongConsumer b, Spliterator.OfLong splTop) {
        Spliterator.OfLong spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }

    static void mixedTraverseAndSplit(DoubleConsumer b, Spliterator.OfDouble splTop) {
        Spliterator.OfDouble spl1, spl2, spl3;
        splTop.tryAdvance(b);
        spl2 = splTop.trySplit();
        if (spl2 != null) {
            spl2.tryAdvance(b);
            spl1 = spl2.trySplit();
            if (spl1 != null) {
                spl1.tryAdvance(b);
                spl1.forEachRemaining(b);
            }
            spl2.tryAdvance(b);
            spl2.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        spl3 = splTop.trySplit();
        if (spl3 != null) {
            spl3.tryAdvance(b);
            spl3.forEachRemaining(b);
        }
        splTop.tryAdvance(b);
        splTop.forEachRemaining(b);
    }
}
