// Path: src/main/java/com/jordanwilliams/heftydb/data/Tuple.java
// public class Tuple implements Comparable<Tuple> {
// 
//     public static Serializer<Tuple> SERIALIZER = new Serializer<Tuple>() {
//         @Override
//         public int size(Tuple tuple) {
//             int size = 0;
// 
//             //Key
//             size += Sizes.INT_SIZE;
//             size += tuple.key().size();
//             size += Sizes.LONG_SIZE;
// 
//             //Value
//             size += Sizes.INT_SIZE;
//             size += tuple.value().size();
// 
//             return size;
//         }
// 
//         @Override
//         public void serialize(Tuple tuple, ByteBuffer recordBuffer) {
//             //Key
//             recordBuffer.putInt(tuple.key.size());
//             recordBuffer.put(tuple.key.data());
//             recordBuffer.putLong(tuple.key.snapshotId());
//             tuple.key().data().rewind();
// 
//             //Value
//             recordBuffer.putInt(tuple.value.size());
//             recordBuffer.put(tuple.value().data());
//             tuple.value().data().rewind();
// 
//             recordBuffer.rewind();
//         }
// 
//         @Override
//         public Tuple deserialize(ByteBuffer recordBuffer) {
//             //Key
//             int keySize = recordBuffer.getInt();
//             ByteBuffer keyBuffer = ByteBuffer.allocate(keySize);
//             recordBuffer.get(keyBuffer.array());
//             long snapshotId = recordBuffer.getLong();
//             Key key = new Key(keyBuffer, snapshotId);
// 
//             //Value
//             int valueSize = recordBuffer.getInt();
//             ByteBuffer valueBuffer = ByteBuffer.allocate(valueSize);
//             recordBuffer.get(valueBuffer.array());
//             Value value = new Value(valueBuffer);
// 
//             return new Tuple(key, value);
//         }
//     };
// 
//     private final Key key;
//     private final Value value;
// 
//     public Tuple(Key key, Value value) {
//         this.key = key;
//         this.value = value;
//     }
// 
//     public Key key() {
//         return key;
//     }
// 
//     public Value value() {
//         return value;
//     }
// 
//     public int size() {
//         return key.size() + value().size();
//     }
// 
//     public void rewind() {
//         key.data().rewind();
//         value.data().rewind();
//     }
// 
//     @Override
//     public int compareTo(Tuple o) {
//         return key.compareTo(o.key);
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Tuple tuple = (Tuple) o;
// 
//         if (key != null ? !key.equals(tuple.key) : tuple.key != null) return false;
//         if (value != null ? !value.equals(tuple.value) : tuple.value != null) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = key != null ? key.hashCode() : 0;
//         result = 31 * result + (value != null ? value.hashCode() : 0);
//         return result;
//     }
// 
//     @Override
//     public String toString() {
//         return "Tuple{" +
//                 "key=" + key +
//                 ", value=" + value +
//                 '}';
//     }
// }
// 
// Path: src/main/java/com/jordanwilliams/heftydb/util/CloseableIterator.java
// public interface CloseableIterator<T> extends Iterator<T>, Closeable {
// 
//     public static class Wrapper<T> implements CloseableIterator<T> {
// 
//         private final Iterator<T> delegate;
// 
//         public Wrapper(Iterator<T> delegate) {
//             this.delegate = delegate;
//         }
// 
//         @Override
//         public void close() throws IOException {
// 
//         }
// 
//         @Override
//         public boolean hasNext() {
//             return delegate.hasNext();
//         }
// 
//         @Override
//         public T next() {
//             return delegate.next();
//         }
// 
//         @Override
//         public void remove() {
//             delegate.remove();
//         }
//     }
// 
// }


import com.jordanwilliams.heftydb.data.Tuple;
import com.jordanwilliams.heftydb.util.CloseableIterator;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.SortedSet;
import java.util.TreeSet;
        if (!fetchNextTuples()){
            return false;
        }

        return true;
    }

    @Override
    public Tuple next() {
        if (nextTuples.isEmpty()) {
            hasNext();
        }

        return nextTuples.poll();
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void close() throws IOException {
        tupleIterator.close();
    }

    private boolean fetchNextTuples() {
        while (tupleIterator.hasNext()) {
            Tuple next = tupleIterator.next();

// Path: src/main/java/com/jordanwilliams/heftydb/data/Tuple.java
// public class Tuple implements Comparable<Tuple> {
// 
//     public static Serializer<Tuple> SERIALIZER = new Serializer<Tuple>() {
//         @Override
//         public int size(Tuple tuple) {
//             int size = 0;
// 
//             //Key
//             size += Sizes.INT_SIZE;
//             size += tuple.key().size();
//             size += Sizes.LONG_SIZE;
// 
//             //Value
//             size += Sizes.INT_SIZE;
//             size += tuple.value().size();
// 
//             return size;
//         }
// 
//         @Override
//         public void serialize(Tuple tuple, ByteBuffer recordBuffer) {
//             //Key
//             recordBuffer.putInt(tuple.key.size());
//             recordBuffer.put(tuple.key.data());
//             recordBuffer.putLong(tuple.key.snapshotId());
//             tuple.key().data().rewind();
// 
//             //Value
//             recordBuffer.putInt(tuple.value.size());
//             recordBuffer.put(tuple.value().data());
//             tuple.value().data().rewind();
// 
//             recordBuffer.rewind();
//         }
// 
//         @Override
//         public Tuple deserialize(ByteBuffer recordBuffer) {
//             //Key
//             int keySize = recordBuffer.getInt();
//             ByteBuffer keyBuffer = ByteBuffer.allocate(keySize);
//             recordBuffer.get(keyBuffer.array());
//             long snapshotId = recordBuffer.getLong();
//             Key key = new Key(keyBuffer, snapshotId);
// 
//             //Value
//             int valueSize = recordBuffer.getInt();
//             ByteBuffer valueBuffer = ByteBuffer.allocate(valueSize);
//             recordBuffer.get(valueBuffer.array());
//             Value value = new Value(valueBuffer);
// 
//             return new Tuple(key, value);
//         }
//     };
// 
//     private final Key key;
//     private final Value value;
// 
//     public Tuple(Key key, Value value) {
//         this.key = key;
//         this.value = value;
//     }
// 
//     public Key key() {
//         return key;
//     }
// 
//     public Value value() {
//         return value;
//     }
// 
//     public int size() {
//         return key.size() + value().size();
//     }
// 
//     public void rewind() {
//         key.data().rewind();
//         value.data().rewind();
//     }
// 
//     @Override
//     public int compareTo(Tuple o) {
//         return key.compareTo(o.key);
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Tuple tuple = (Tuple) o;
// 
//         if (key != null ? !key.equals(tuple.key) : tuple.key != null) return false;
//         if (value != null ? !value.equals(tuple.value) : tuple.value != null) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = key != null ? key.hashCode() : 0;
//         result = 31 * result + (value != null ? value.hashCode() : 0);
//         return result;
//     }
// 
//     @Override
//     public String toString() {
//         return "Tuple{" +
//                 "key=" + key +
//                 ", value=" + value +
//                 '}';
//     }
// }
// 
// Path: src/main/java/com/jordanwilliams/heftydb/util/CloseableIterator.java
// public interface CloseableIterator<T> extends Iterator<T>, Closeable {
// 
//     public static class Wrapper<T> implements CloseableIterator<T> {
// 
//         private final Iterator<T> delegate;
// 
//         public Wrapper(Iterator<T> delegate) {
//             this.delegate = delegate;
//         }
// 
//         @Override
//         public void close() throws IOException {
// 
//         }
// 
//         @Override
//         public boolean hasNext() {
//             return delegate.hasNext();
//         }
// 
//         @Override
//         public T next() {
//             return delegate.next();
//         }
// 
//         @Override
//         public void remove() {
//             delegate.remove();
//         }
//     }
// 
// }


// Path: src/main/java/com/jordanwilliams/heftydb/read/CompactionTupleIterator.java
import com.jordanwilliams.heftydb.data.Tuple;
import com.jordanwilliams.heftydb.util.CloseableIterator;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.SortedSet;
import java.util.TreeSet;

        if (!fetchNextTuples()){
            return false;
        }

        return true;
    }

    @Override
    public Tuple next() {
        if (nextTuples.isEmpty()) {
            hasNext();
        }

        return nextTuples.poll();
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void close() throws IOException {
        tupleIterator.close();
    }

    private boolean fetchNextTuples() {
        while (tupleIterator.hasNext()) {
            Tuple next = tupleIterator.next();

            boolean nextKeyEqualCurrent = currentKeyTuples.isEmpty() || next.key().data().equals(currentKeyTuples