// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// static <T> Collector<T, ?, TinyContainer<T>> toTinyContainer() {
//   return Collector.of(TinyContainer::new, TinyContainer::add, TinyContainer::addAll);
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// public static <T> Collector<T, ?, T> onlyElement() {
//   return collectingAndThen(toTinyContainer(), TinyContainer::onlyOne);
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// public static <T, R> Collector<T, ?, R> onlyElements(
//     BiFunction<? super T, ? super T, ? extends R> twoElements) {
//   requireNonNull(twoElements);
//   return collectingAndThen(toTinyContainer(), c -> c.only(twoElements));
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// @SafeVarargs
// public static <T, R> Collector<T, ?, R> cases(
//     Collector<? super T, ?, ? extends Optional<? extends R>>... cases) {
//   List<Collector<? super T, ?, ? extends Optional<? extends R>>> caseList =
//       Arrays.stream(cases).peek(Objects::requireNonNull).collect(toList());
//   return collectingAndThen(
//       toList(),
//       input ->
//           caseList.stream()
//               .map(c -> input.stream().collect(c).orElse(null))
//               .filter(v -> v != null)
//               .findFirst()
//               .orElseThrow(() -> unexpectedSize(input.size())));
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// public static <R> Collector<Object, ?, Optional<R>> when(Supplier<? extends R> noElement) {
//   requireNonNull(noElement);
//   return collectingAndThen(
//       counting(), c -> c == 0 ? Optional.of(noElement.get()) : Optional.empty());
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// static final class TinyContainer<T> {
//   private T first;
//   private T second;
//   private int size = 0;
// 
//   static <T> Collector<T, ?, TinyContainer<T>> toTinyContainer() {
//     return Collector.of(TinyContainer::new, TinyContainer::add, TinyContainer::addAll);
//   }
// 
//   void add(T value) {
//     if (size == 0) {
//       first = value;
//     } else if (size == 1) {
//       second = value;
//     }
//     size++;
//   }
// 
//   // Hate to write this code! But a combiner is upon us whether we want parallel or not.
//   TinyContainer<T> addAll(TinyContainer<? extends T> that) {
//     int newSize = size + that.size;
//     if (that.size > 0) {
//       add(that.first);
//     }
//     if (that.size > 1) {
//       add(that.second);
//     }
//     size = newSize;
//     return this;
//   }
// 
//   int size() {
//     return size;
//   }
// 
//   <R> Optional<R> when(
//       Predicate<? super T> condition, Function<? super T, ? extends R> oneElement) {
//     return size == 1 && condition.test(first)
//         ? Optional.of(oneElement.apply(first))
//         : Optional.empty();
//   }
// 
//   <R> Optional<R> when(
//       BiPredicate<? super T, ? super T> condition,
//       BiFunction<? super T, ? super T, ? extends R> twoElements) {
//     return size == 2 && condition.test(first, second)
//         ? Optional.of(twoElements.apply(first, second))
//         : Optional.empty();
//   }
// 
//   <R> R only(BiFunction<? super T, ? super T, ? extends R> twoElements) {
//     return when((x, y) -> true, twoElements).orElseThrow(() -> unexpectedSize(size));
//   }
// 
//   T onlyOne() {
//     return when(x -> true, identity()).orElseThrow(() -> unexpectedSize(size));
//   }
// }


import static com.google.mu.util.stream.Cases.TinyContainer.toTinyContainer;
import static com.google.mu.util.stream.Cases.onlyElement;
import static com.google.mu.util.stream.Cases.onlyElements;
import static com.google.mu.util.stream.Cases.cases;
import static com.google.mu.util.stream.Cases.when;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static java.util.function.Function.identity;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.testing.NullPointerTester;
import com.google.mu.util.stream.Cases.TinyContainer;
import java.util.stream.Stream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
  }

  @Test public void only_twoElements() {
    int result = Stream.of(2, 3).collect(onlyElements((a, b) -> a * b));
    assertThat(result).isEqualTo(6);
    IllegalArgumentException thrown =
        assertThrows(
            IllegalArgumentException.class, () -> Stream.of(1).collect(onlyElements((a, b) -> a * b)));
    assertThat(thrown).hasMessageThat().contains("size: 1");
  }

  @Test public void cases_firstCaseMatch() {
    String result = Stream.of("foo", "bar").collect(cases(when((a, b) -> a + b), when(a -> a)));
    assertThat(result).isEqualTo("foobar");
  }

  @Test public void cases_secondCaseMatch() {
    String result = Stream.of("foo").collect(cases(when((a, b) -> a + b), when(a -> a)));
    assertThat(result).isEqualTo("foo");
  }

  @Test public void cases_noMatchingCase() {
    IllegalArgumentException thrown =
        assertThrows(
            IllegalArgumentException.class,
            () -> Stream.of(1, 2, 3).collect(cases(when((a, b) -> a + b), when(a -> a))));
    assertThat(thrown).hasMessageThat().contains("size: 3");
  }

  @Test public void toTinyContainer_empty() {
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// static <T> Collector<T, ?, TinyContainer<T>> toTinyContainer() {
//   return Collector.of(TinyContainer::new, TinyContainer::add, TinyContainer::addAll);
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// public static <T> Collector<T, ?, T> onlyElement() {
//   return collectingAndThen(toTinyContainer(), TinyContainer::onlyOne);
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// public static <T, R> Collector<T, ?, R> onlyElements(
//     BiFunction<? super T, ? super T, ? extends R> twoElements) {
//   requireNonNull(twoElements);
//   return collectingAndThen(toTinyContainer(), c -> c.only(twoElements));
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// @SafeVarargs
// public static <T, R> Collector<T, ?, R> cases(
//     Collector<? super T, ?, ? extends Optional<? extends R>>... cases) {
//   List<Collector<? super T, ?, ? extends Optional<? extends R>>> caseList =
//       Arrays.stream(cases).peek(Objects::requireNonNull).collect(toList());
//   return collectingAndThen(
//       toList(),
//       input ->
//           caseList.stream()
//               .map(c -> input.stream().collect(c).orElse(null))
//               .filter(v -> v != null)
//               .findFirst()
//               .orElseThrow(() -> unexpectedSize(input.size())));
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// public static <R> Collector<Object, ?, Optional<R>> when(Supplier<? extends R> noElement) {
//   requireNonNull(noElement);
//   return collectingAndThen(
//       counting(), c -> c == 0 ? Optional.of(noElement.get()) : Optional.empty());
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/Cases.java
// static final class TinyContainer<T> {
//   private T first;
//   private T second;
//   private int size = 0;
// 
//   static <T> Collector<T, ?, TinyContainer<T>> toTinyContainer() {
//     return Collector.of(TinyContainer::new, TinyContainer::add, TinyContainer::addAll);
//   }
// 
//   void add(T value) {
//     if (size == 0) {
//       first = value;
//     } else if (size == 1) {
//       second = value;
//     }
//     size++;
//   }
// 
//   // Hate to write this code! But a combiner is upon us whether we want parallel or not.
//   TinyContainer<T> addAll(TinyContainer<? extends T> that) {
//     int newSize = size + that.size;
//     if (that.size > 0) {
//       add(that.first);
//     }
//     if (that.size > 1) {
//       add(that.second);
//     }
//     size = newSize;
//     return this;
//   }
// 
//   int size() {
//     return size;
//   }
// 
//   <R> Optional<R> when(
//       Predicate<? super T> condition, Function<? super T, ? extends R> oneElement) {
//     return size == 1 && condition.test(first)
//         ? Optional.of(oneElement.apply(first))
//         : Optional.empty();
//   }
// 
//   <R> Optional<R> when(
//       BiPredicate<? super T, ? super T> condition,
//       BiFunction<? super T, ? super T, ? extends R> twoElements) {
//     return size == 2 && condition.test(first, second)
//         ? Optional.of(twoElements.apply(first, second))
//         : Optional.empty();
//   }
// 
//   <R> R only(BiFunction<? super T, ? super T, ? extends R> twoElements) {
//     return when((x, y) -> true, twoElements).orElseThrow(() -> unexpectedSize(size));
//   }
// 
//   T onlyOne() {
//     return when(x -> true, identity()).orElseThrow(() -> unexpectedSize(size));
//   }
// }


// Path: mug/src/test/java/com/google/mu/util/stream/CasesTest.java
import static com.google.mu.util.stream.Cases.TinyContainer.toTinyContainer;
import static com.google.mu.util.stream.Cases.onlyElement;
import static com.google.mu.util.stream.Cases.onlyElements;
import static com.google.mu.util.stream.Cases.cases;
import static com.google.mu.util.stream.Cases.when;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static java.util.function.Function.identity;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.testing.NullPointerTester;
import com.google.mu.util.stream.Cases.TinyContainer;
import java.util.stream.Stream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

  }

  @Test public void only_twoElements() {
    int result = Stream.of(2, 3).collect(onlyElements((a, b) -> a * b));
    assertThat(result).isEqualTo(6);
    IllegalArgumentException thrown =
        assertThrows(
            IllegalArgumentException.class, () -> Stream.of(1).collect(onlyElements((a, b) -> a * b)));
    assertThat(thrown).hasMessageThat().contains("size: 1");
  }

  @Test public void cases_firstCaseMatch() {
    String result = Stream.of("foo", "bar").collect(cases(when((a, b) -> a + b), when(a -> a)));
    assertThat(result).isEqualTo("foobar");
  }

  @Test public void cases_secondCaseMatch() {
    String result = Stream.of("foo").collect(cases(when((a, b) -> a + b), when(a -> a)));
    assertThat(result).isEqualTo("foo");
  }

  @Test public void cases_noMatchingCase() {
    IllegalArgumentException thrown =
        assertThrows(
            IllegalArgumentException.class,
            () -> Stream.of(1, 2, 3).collect(cases(when((a, b) -> a + b), when(a -> a))));
    assertThat(thrown).hasMessageThat().contains("size: 3");
  }

  @Test public void toTinyContainer_empty() {
    assertThat(Stream.empty().collect(toTinyContainer()).size()).isEqualTo(0);