// 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/ByteBuffers.java
// public class ByteBuffers {
// 
//     public static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
// 
//     public static ByteBuffer fromString(String string) {
//         return ByteBuffer.wrap(string.getBytes(Charset.defaultCharset()));
//     }
// 
//     public static String toString(ByteBuffer byteBuffer) {
//         byte[] bytes = new byte[byteBuffer.capacity()];
// 
//         for (int i = 0; i < byteBuffer.capacity(); i++) {
//             bytes[i] = byteBuffer.get(i);
//         }
// 
//         return new String(bytes);
//     }
// }
// 
// 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.ByteBuffers;
import com.jordanwilliams.heftydb.util.CloseableIterator;
import java.io.IOException;
import java.nio.ByteBuffer;
/*
 * Copyright (c) 2014. Jordan Williams
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jordanwilliams.heftydb.db;



/**
 * A public wrapper class that represents the results of a database read.
 */
public class Record implements Comparable<Record> {

    public static class TupleIterator implements CloseableIterator<Record> {

        private final CloseableIterator<Tuple> tupleIterator;

        public TupleIterator(CloseableIterator<Tuple> tupleIterator) {
            this.tupleIterator = tupleIterator;
        }

        @Override
        public boolean hasNext() {
            return tupleIterator.hasNext();
        }

        @Override
        public Record next() {
            return new Record(tupleIterator.next());
        }

        @Override
        public void remove() {
            tupleIterator.remove();
        }

        @Override
// 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/ByteBuffers.java
// public class ByteBuffers {
// 
//     public static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
// 
//     public static ByteBuffer fromString(String string) {
//         return ByteBuffer.wrap(string.getBytes(Charset.defaultCharset()));
//     }
// 
//     public static String toString(ByteBuffer byteBuffer) {
//         byte[] bytes = new byte[byteBuffer.capacity()];
// 
//         for (int i = 0; i < byteBuffer.capacity(); i++) {
//             bytes[i] = byteBuffer.get(i);
//         }
// 
//         return new String(bytes);
//     }
// }
// 
// 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/db/Record.java
import com.jordanwilliams.heftydb.data.Tuple;
import com.jordanwilliams.heftydb.util.ByteBuffers;
import com.jordanwilliams.heftydb.util.CloseableIterator;
import java.io.IOException;
import java.nio.ByteBuffer;

/*
 * Copyright (c) 2014. Jordan Williams
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jordanwilliams.heftydb.db;



/**
 * A public wrapper class that represents the results of a database read.
 */
public class Record implements Comparable<Record> {

    public static class TupleIterator implements CloseableIterator<Record> {

        private final CloseableIterator<Tuple> tupleIterator;

        public TupleIterator(CloseableIterator<Tuple> tupleIterator) {
            this.tupleIterator = tupleIterator;
        }

        @Override
        public boolean hasNext() {
            return tupleIterator.hasNext();
        }

        @Override
        public Record next() {
            return new Record(tupleIterator.next());
        }

        @Override
        public void remove() {
            tupleIterator.remove();
        }

        @Override
        public void close() throws IOException {