// Path: src/main/java/com/noodlesandwich/streams/EndOfStreamException.java
// public final class EndOfStreamException extends RuntimeException {
//     private static final long serialVersionUID = 6349624304997685948L;
// 
//     public EndOfStreamException() {
//         super("End of stream");
//     }
// }
// 
// Path: src/main/java/com/noodlesandwich/streams/Streams.java
// public final class Streams {
//     private Streams() {
//     }
// 
//     /**
//      * Creates an empty stream. Attempts to call {@link Stream#head()} or {@link Stream#tail()} on this stream will
//      * throw an {@link EndOfStreamException}.
//      */
//     public static <T> Stream<T> nil() {
//         return new Nil<>();
//     }
// 
//     /**
//      * Creates an empty stream of the type provided. Attempts to call {@link Stream#head()} or {@link Stream#tail()} on
//      * this stream will throw an {@link EndOfStreamException}.
//      */
//     public static <T> Stream<T> nil(@SuppressWarnings("unused") final Class<T> type) {
//         return new Nil<>();
//     }
// 
//     /**
//      * <p>Creates a new stream by prepending <code>head</code> to <code>tail</code>. Can be nested to build up a large
//      * stream. It is expected that the final value in the chain will be {@link #nil()}.</p>
//      *
//      * <p><strong>Example:</strong></p>
//      * <blockquote>
//      * <code>cons(a, cons(b, cons(c, nil())))</code> will return a stream that when iterated over, will yield
//      * <code>a</code>, then <code>b</code>, then <code>c</code>.
//      * </blockquote>
//      */
//     public static <T> Stream<T> cons(final T head, final Stream<T> tail) {
//         return new Cons<>(head, tail);
//     }
// 
//     /**
//      * Creates a new stream over the values provided. This is shorthand for nested calls to {@link #cons}.
//      */
//     @SafeVarargs
//     public static <T> Stream<T> of(final T... items) {
//         return clone(Iterators.forArray(items));
//     }
// 
//     /**
//      * Clones an iterable by iterating over it and building up a stream.
//      */
//     public static <T> Stream<T> clone(final Iterable<T> iterable) {
//         return clone(iterable.iterator());
//     }
// 
//     public static <T> Stream<T> clone(final Iterator<T> iterator) {
//         if (!iterator.hasNext()) {
//             return nil();
//         }
// 
//         return cons(iterator.next(), clone(iterator));
//     }
// 
//     /**
//      * Wraps an iterable. Delegates to {@link #wrap(java.util.Iterator) wrap(Iterator&lt;T&gt;)}.
//      */
//     public static <T> Stream<T> wrap(final Iterable<T> iterable) {
//         return wrap(iterable.iterator());
//     }
// 
//     /**
//      * Wraps an iterator with a stream that retains values as they are retrieved, ensuring the stream can be iterated
//      * over multiple times.
//      */
//     public static <T> Stream<T> wrap(final Iterator<T> iterator) {
//         return new IteratorWrapper<>(iterator);
//     }
// 
//     /**
//      * Generates a stream using a function that is applied to each successive element, starting with the start value
//      * provided. This stream will normally be infinite, but the iterating function can terminate it by throwing an
//      * {@link EndOfStreamException}.
//      */
//     public static <T> Stream<T> generate(final Function<? super T, ? extends T> iteratingFunction, final T start) {
//         return new Generator<>(iteratingFunction, start);
//     }
// 
//     /**
//      * Generates an infinite stream by repeating the value provided.
//      */
//     public static <T> Stream<T> repeat(final T value) {
//         return generate(identity(), value);
//     }
// }
// 
// Path: src/test/java/com/noodlesandwich/streams/matchers/NilMatcher.java
// public static <T> NilMatcher<T> nil() {
//     return new NilMatcher<>();
// }


import org.junit.jupiter.api.Test;
import com.noodlesandwich.streams.EndOfStreamException;
import com.noodlesandwich.streams.Streams;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static com.noodlesandwich.streams.matchers.NilMatcher.nil;
package com.noodlesandwich.streams.implementations;





public final class NilTest {
    @Test public void
    nil_is_nil() {
        assertThat(Streams.nil(), is(nil()));
    }

    @Test public void
    throws_an_exception_if_head_is_called() {
        assertThrows(EndOfStreamException.class, () -> Streams.nil().head());
    }

    @Test public void
    throws_an_exception_if_tail_is_called() {
// Path: src/main/java/com/noodlesandwich/streams/EndOfStreamException.java
// public final class EndOfStreamException extends RuntimeException {
//     private static final long serialVersionUID = 6349624304997685948L;
// 
//     public EndOfStreamException() {
//         super("End of stream");
//     }
// }
// 
// Path: src/main/java/com/noodlesandwich/streams/Streams.java
// public final class Streams {
//     private Streams() {
//     }
// 
//     /**
//      * Creates an empty stream. Attempts to call {@link Stream#head()} or {@link Stream#tail()} on this stream will
//      * throw an {@link EndOfStreamException}.
//      */
//     public static <T> Stream<T> nil() {
//         return new Nil<>();
//     }
// 
//     /**
//      * Creates an empty stream of the type provided. Attempts to call {@link Stream#head()} or {@link Stream#tail()} on
//      * this stream will throw an {@link EndOfStreamException}.
//      */
//     public static <T> Stream<T> nil(@SuppressWarnings("unused") final Class<T> type) {
//         return new Nil<>();
//     }
// 
//     /**
//      * <p>Creates a new stream by prepending <code>head</code> to <code>tail</code>. Can be nested to build up a large
//      * stream. It is expected that the final value in the chain will be {@link #nil()}.</p>
//      *
//      * <p><strong>Example:</strong></p>
//      * <blockquote>
//      * <code>cons(a, cons(b, cons(c, nil())))</code> will return a stream that when iterated over, will yield
//      * <code>a</code>, then <code>b</code>, then <code>c</code>.
//      * </blockquote>
//      */
//     public static <T> Stream<T> cons(final T head, final Stream<T> tail) {
//         return new Cons<>(head, tail);
//     }
// 
//     /**
//      * Creates a new stream over the values provided. This is shorthand for nested calls to {@link #cons}.
//      */
//     @SafeVarargs
//     public static <T> Stream<T> of(final T... items) {
//         return clone(Iterators.forArray(items));
//     }
// 
//     /**
//      * Clones an iterable by iterating over it and building up a stream.
//      */
//     public static <T> Stream<T> clone(final Iterable<T> iterable) {
//         return clone(iterable.iterator());
//     }
// 
//     public static <T> Stream<T> clone(final Iterator<T> iterator) {
//         if (!iterator.hasNext()) {
//             return nil();
//         }
// 
//         return cons(iterator.next(), clone(iterator));
//     }
// 
//     /**
//      * Wraps an iterable. Delegates to {@link #wrap(java.util.Iterator) wrap(Iterator&lt;T&gt;)}.
//      */
//     public static <T> Stream<T> wrap(final Iterable<T> iterable) {
//         return wrap(iterable.iterator());
//     }
// 
//     /**
//      * Wraps an iterator with a stream that retains values as they are retrieved, ensuring the stream can be iterated
//      * over multiple times.
//      */
//     public static <T> Stream<T> wrap(final Iterator<T> iterator) {
//         return new IteratorWrapper<>(iterator);
//     }
// 
//     /**
//      * Generates a stream using a function that is applied to each successive element, starting with the start value
//      * provided. This stream will normally be infinite, but the iterating function can terminate it by throwing an
//      * {@link EndOfStreamException}.
//      */
//     public static <T> Stream<T> generate(final Function<? super T, ? extends T> iteratingFunction, final T start) {
//         return new Generator<>(iteratingFunction, start);
//     }
// 
//     /**
//      * Generates an infinite stream by repeating the value provided.
//      */
//     public static <T> Stream<T> repeat(final T value) {
//         return generate(identity(), value);
//     }
// }
// 
// Path: src/test/java/com/noodlesandwich/streams/matchers/NilMatcher.java
// public static <T> NilMatcher<T> nil() {
//     return new NilMatcher<>();
// }


// Path: src/test/java/com/noodlesandwich/streams/implementations/NilTest.java
import org.junit.jupiter.api.Test;
import com.noodlesandwich.streams.EndOfStreamException;
import com.noodlesandwich.streams.Streams;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static com.noodlesandwich.streams.matchers.NilMatcher.nil;

package com.noodlesandwich.streams.implementations;





public final class NilTest {
    @Test public void
    nil_is_nil() {
        assertThat(Streams.nil(), is(nil()));
    }

    @Test public void
    throws_an_exception_if_head_is_called() {
        assertThrows(EndOfStreamException.class, () -> Streams.nil().head());
    }

    @Test public void
    throws_an_exception_if_tail_is_called() {
        assertThrows(EndOfStreamException.class, () -> Streams.nil().tail());