// Path: src/main/java/uk/elementarysoftware/quickcsv/api/ByteArraySource.java
// public static class ByteArrayChunk extends ReusableChunk {
//     public static final ByteArrayChunk EMPTY = new ByteArrayChunk(new byte[0], 0, false, (b) -> {});
//         
//     private final byte[] data;
//     private final int length;
//     private final boolean isLast;
// 
//     /**
//      * @param data - underlying content
//      * @param length - content length
//      * @param isLast - is this chunk of is last
//      * @param onFree - callback that will be called when data from this chunk has been fully consumed.
//      */
//     public ByteArrayChunk(byte[] data, int length, boolean isLast, Consumer<byte[]> onFree) {
//         super(() -> onFree.accept(data));
//         this.data = data;
//         this.length = length;
//         this.isLast = isLast;
//     }
// 
//     public byte[] getData() {
//         return data;
//     }
// 
//     public int getLength() {
//         return length;
//     }
// 
//     public boolean isLast() {
//         return isLast;
//     }
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/api/CSVParserBuilder.java
// public static class CSVFileMetadata {
//         
//     public static CSVFileMetadata RFC_4180 = new CSVFileMetadata(',', Optional.of('"'));
//     public static CSVFileMetadata TABS = new CSVFileMetadata('\t', Optional.empty());
//         
//     public final char separator;
//     public final Optional<Character> quote;
// 
//     public CSVFileMetadata(char separator, Optional<Character> quote) {
//         this.separator = separator;
//         this.quote = quote;
//     }
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/Pair.java
// public class Pair<F, S> {
//     
//     public final F first;
//     public final S second;
// 
//     /**
//      * Constructor for a Pair.
//      *
//      * @param first the first object in the Pair
//      * @param second the second object in the pair
//      */
//     public Pair(F first, S second) {
//         this.first = first;
//         this.second = second;
//     }
// 
//     /**
//      * Checks the two objects for equality by delegating to their respective
//      * {@link Object#equals(Object)} methods.
//      *
//      * @param o the {@link Pair} to which this one is to be checked for equality
//      * @return true if the underlying objects of the Pair are both considered
//      *         equal
//      */
//     @Override
//     public boolean equals(Object o) {
//         if (!(o instanceof Pair)) {
//             return false;
//         }
//         Pair<?, ?> p = (Pair<?, ?>) o;
//         return Objects.equals(p.first, first) && Objects.equals(p.second, second);
//     }
// 
//     /**
//      * Compute a hash code using the hash codes of the underlying objects
//      *
//      * @return a hashcode of the Pair
//      */
//     @Override
//     public int hashCode() {
//         return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
//     }
//     
//     @Override
//     public String toString() {
//         return first+"="+second;
//     }
// 
//     /**
//      * Convenience method for creating an appropriately typed pair.
//      * @param a the first object in the Pair
//      * @param b the second object in the pair
//      * @param <A> type of left element
//      * @param <B> type of right element
//      * @return a Pair that is templatized with the types of a and b
//      */
//     public static <A, B> Pair <A, B> of(A a, B b) {
//         return new Pair<A, B>(a, b);
//     }
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunBiCharToBoolean {
//     public boolean apply(char c, char q);
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunBiCharToT<T> {
//     public T apply(char c, char q);
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunCharToBoolean {
//     public boolean apply(char c);
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunCharToT<T> {
//     public T apply(char c);
// }


import java.nio.charset.Charset;
import uk.elementarysoftware.quickcsv.api.ByteArraySource.ByteArrayChunk;
import uk.elementarysoftware.quickcsv.api.CSVParserBuilder.CSVFileMetadata;
import uk.elementarysoftware.quickcsv.functional.Pair;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunBiCharToBoolean;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunBiCharToT;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunCharToBoolean;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunCharToT;
            return suffix.skipUntil(c);
        }
    }

    private boolean skipUntilWithPrefix(char c, char q) {
        if (prefix.isEmpty()) {
            flip();
            return suffix.skipUntil(c, q);
        }
        boolean isFound = prefix.skipUntil(c, q);
        if (isFound) {
            return true;
        } else {
            return suffix.skipUntil(c, q);
        }
    }

    private void flip() {
        this.nextFieldFun =  suffix::nextField;
        this.nextFieldFunQuoted =  suffix::nextField;
        this.skipUntilFun = suffix::skipUntil;
        this.skipUntilFunQuoted = suffix::skipUntil;
    }
    /*
     * -----------------------------------------------------------
     * end
     * -----------------------------------------------------------
    */

    @Override
// Path: src/main/java/uk/elementarysoftware/quickcsv/api/ByteArraySource.java
// public static class ByteArrayChunk extends ReusableChunk {
//     public static final ByteArrayChunk EMPTY = new ByteArrayChunk(new byte[0], 0, false, (b) -> {});
//         
//     private final byte[] data;
//     private final int length;
//     private final boolean isLast;
// 
//     /**
//      * @param data - underlying content
//      * @param length - content length
//      * @param isLast - is this chunk of is last
//      * @param onFree - callback that will be called when data from this chunk has been fully consumed.
//      */
//     public ByteArrayChunk(byte[] data, int length, boolean isLast, Consumer<byte[]> onFree) {
//         super(() -> onFree.accept(data));
//         this.data = data;
//         this.length = length;
//         this.isLast = isLast;
//     }
// 
//     public byte[] getData() {
//         return data;
//     }
// 
//     public int getLength() {
//         return length;
//     }
// 
//     public boolean isLast() {
//         return isLast;
//     }
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/api/CSVParserBuilder.java
// public static class CSVFileMetadata {
//         
//     public static CSVFileMetadata RFC_4180 = new CSVFileMetadata(',', Optional.of('"'));
//     public static CSVFileMetadata TABS = new CSVFileMetadata('\t', Optional.empty());
//         
//     public final char separator;
//     public final Optional<Character> quote;
// 
//     public CSVFileMetadata(char separator, Optional<Character> quote) {
//         this.separator = separator;
//         this.quote = quote;
//     }
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/Pair.java
// public class Pair<F, S> {
//     
//     public final F first;
//     public final S second;
// 
//     /**
//      * Constructor for a Pair.
//      *
//      * @param first the first object in the Pair
//      * @param second the second object in the pair
//      */
//     public Pair(F first, S second) {
//         this.first = first;
//         this.second = second;
//     }
// 
//     /**
//      * Checks the two objects for equality by delegating to their respective
//      * {@link Object#equals(Object)} methods.
//      *
//      * @param o the {@link Pair} to which this one is to be checked for equality
//      * @return true if the underlying objects of the Pair are both considered
//      *         equal
//      */
//     @Override
//     public boolean equals(Object o) {
//         if (!(o instanceof Pair)) {
//             return false;
//         }
//         Pair<?, ?> p = (Pair<?, ?>) o;
//         return Objects.equals(p.first, first) && Objects.equals(p.second, second);
//     }
// 
//     /**
//      * Compute a hash code using the hash codes of the underlying objects
//      *
//      * @return a hashcode of the Pair
//      */
//     @Override
//     public int hashCode() {
//         return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
//     }
//     
//     @Override
//     public String toString() {
//         return first+"="+second;
//     }
// 
//     /**
//      * Convenience method for creating an appropriately typed pair.
//      * @param a the first object in the Pair
//      * @param b the second object in the pair
//      * @param <A> type of left element
//      * @param <B> type of right element
//      * @return a Pair that is templatized with the types of a and b
//      */
//     public static <A, B> Pair <A, B> of(A a, B b) {
//         return new Pair<A, B>(a, b);
//     }
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunBiCharToBoolean {
//     public boolean apply(char c, char q);
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunBiCharToT<T> {
//     public T apply(char c, char q);
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunCharToBoolean {
//     public boolean apply(char c);
// }
// 
// Path: src/main/java/uk/elementarysoftware/quickcsv/functional/PrimitiveFunctions.java
// @FunctionalInterface
// public static interface FunCharToT<T> {
//     public T apply(char c);
// }


// Path: src/main/java/uk/elementarysoftware/quickcsv/parser/ByteSlice.java
import java.nio.charset.Charset;
import uk.elementarysoftware.quickcsv.api.ByteArraySource.ByteArrayChunk;
import uk.elementarysoftware.quickcsv.api.CSVParserBuilder.CSVFileMetadata;
import uk.elementarysoftware.quickcsv.functional.Pair;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunBiCharToBoolean;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunBiCharToT;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunCharToBoolean;
import uk.elementarysoftware.quickcsv.functional.PrimitiveFunctions.FunCharToT;

            return suffix.skipUntil(c);
        }
    }

    private boolean skipUntilWithPrefix(char c, char q) {
        if (prefix.isEmpty()) {
            flip();
            return suffix.skipUntil(c, q);
        }
        boolean isFound = prefix.skipUntil(c, q);
        if (isFound) {
            return true;
        } else {
            return suffix.skipUntil(c, q);
        }
    }

    private void flip() {
        this.nextFieldFun =  suffix::nextField;
        this.nextFieldFunQuoted =  suffix::nextField;
        this.skipUntilFun = suffix::skipUntil;
        this.skipUntilFunQuoted = suffix::skipUntil;
    }
    /*
     * -----------------------------------------------------------
     * end
     * -----------------------------------------------------------
    */

    @Override
    public Pair<ByteSlice, ByteSlice> splitOnLastLineEnd() {