// Path: src/main/java/net/amygdalum/stringsearchalgorithms/search/StringFinder.java
// public interface StringFinder {
// 
// 	/**
// 	 * @return the next match in the given document, the order of the matches is determined by the specific implementation
// 	 */
// 	StringMatch findNext();
// 	/**
// 	 * @return all matches in the given document, dependent on the specific implementation some matches may be skipped
// 	 */
// 	List<StringMatch> findAll();
// 	/**
// 	 * skips the document to a specific position (ignoring any match before this position)
// 	 * @param pos the new position to start with
// 	 */
// 	void skipTo(long pos);
// }
// 
// Path: src/main/java/net/amygdalum/stringsearchalgorithms/search/StringFinderOption.java
// public interface StringFinderOption {
// 
// }


import static java.util.Arrays.asList;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import net.amygdalum.stringsearchalgorithms.search.SearchFor;
import net.amygdalum.stringsearchalgorithms.search.StringFinder;
import net.amygdalum.stringsearchalgorithms.search.StringFinderOption;
import net.amygdalum.util.io.ByteProvider;
import net.amygdalum.util.io.StringByteProvider;
				if (!failures.isEmpty()) {
					AssertionError ne = new AssertionError(computeMessage(failures));
					ne.setStackTrace(stackTrace);
					throw ne;
				}
			}

		};
	}

	private String[] extractPattern(final Description description) throws AssertionError {
		SearchFor searchFor = description.getAnnotation(SearchFor.class);
		if (searchFor == null) {
			throw new AssertionError("expected @SearchFor annotation");
		}
		return searchFor.value();
	}

	private String computeMessage(Map<StringSearchAlgorithm, String> failures) {
		StringBuilder buffer = new StringBuilder();
		for (Map.Entry<StringSearchAlgorithm, String> entry : failures.entrySet()) {
			buffer.append("in algorithm <").append(entry.getKey().getClass().getSimpleName()).append(">: ").append(entry.getValue()).append("\n");
		}
		return buffer.toString();
	}

	public StringFinder createSearcher(String chars, StringFinderOption... options) {
		return createSearcher(new StringByteProvider(chars, 0), options);
	}
	
// Path: src/main/java/net/amygdalum/stringsearchalgorithms/search/StringFinder.java
// public interface StringFinder {
// 
// 	/**
// 	 * @return the next match in the given document, the order of the matches is determined by the specific implementation
// 	 */
// 	StringMatch findNext();
// 	/**
// 	 * @return all matches in the given document, dependent on the specific implementation some matches may be skipped
// 	 */
// 	List<StringMatch> findAll();
// 	/**
// 	 * skips the document to a specific position (ignoring any match before this position)
// 	 * @param pos the new position to start with
// 	 */
// 	void skipTo(long pos);
// }
// 
// Path: src/main/java/net/amygdalum/stringsearchalgorithms/search/StringFinderOption.java
// public interface StringFinderOption {
// 
// }


// Path: src/test/java/net/amygdalum/stringsearchalgorithms/search/bytes/MultiStringSearchRule.java
import static java.util.Arrays.asList;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import net.amygdalum.stringsearchalgorithms.search.SearchFor;
import net.amygdalum.stringsearchalgorithms.search.StringFinder;
import net.amygdalum.stringsearchalgorithms.search.StringFinderOption;
import net.amygdalum.util.io.ByteProvider;
import net.amygdalum.util.io.StringByteProvider;

				if (!failures.isEmpty()) {
					AssertionError ne = new AssertionError(computeMessage(failures));
					ne.setStackTrace(stackTrace);
					throw ne;
				}
			}

		};
	}

	private String[] extractPattern(final Description description) throws AssertionError {
		SearchFor searchFor = description.getAnnotation(SearchFor.class);
		if (searchFor == null) {
			throw new AssertionError("expected @SearchFor annotation");
		}
		return searchFor.value();
	}

	private String computeMessage(Map<StringSearchAlgorithm, String> failures) {
		StringBuilder buffer = new StringBuilder();
		for (Map.Entry<StringSearchAlgorithm, String> entry : failures.entrySet()) {
			buffer.append("in algorithm <").append(entry.getKey().getClass().getSimpleName()).append(">: ").append(entry.getValue()).append("\n");
		}
		return buffer.toString();
	}

	public StringFinder createSearcher(String chars, StringFinderOption... options) {
		return createSearcher(new StringByteProvider(chars, 0), options);
	}
	
	public StringFinder createSearcher(ByteProvider bytes, StringFinderOption... options) {