// Path: src/main/java/com/urbanairship/datacube/CSerializable.java
// public interface CSerializable {
//     byte[] serialize();
// }
// 
// Path: src/main/java/com/urbanairship/datacube/Util.java
// public class Util {
//     public static byte[] longToBytes(long l) {
//         return ByteBuffer.allocate(8).putLong(l).array();
//     }
// 
//     /**
//      * Write a big-endian integer into the least significant bytes of a byte array.
//      */
//     public static byte[] intToBytesWithLen(int x, int len) {
//         if(len <= 4) {
//             return trailingBytes(intToBytes(x), len);
//         } else {
//             ByteBuffer bb = ByteBuffer.allocate(len);
//             bb.position(len-4);
//             bb.putInt(x);
//             assert bb.remaining() == 0;
//             return bb.array();
//         }
//     }
// 
//     public static long bytesToLong(byte[] bytes) {
//         if(bytes.length < 8) {
//             throw new IllegalArgumentException("Input array was too small: " +
//                     Arrays.toString(bytes));
//         }
//         
//         return ByteBuffer.wrap(bytes).getLong();
//     }
//     
//     /**
//      * Call this if you have a byte array to convert to long, but your array might need
//      * to be left-padded with zeros (if it is less than 8 bytes long). 
//      */
//     public static long bytesToLongPad(byte[] bytes) {
//         final int padZeros = Math.max(8-bytes.length, 0);
//         ByteBuffer bb = ByteBuffer.allocate(8);
//         for(int i=0; i<padZeros; i++) {
//             bb.put((byte)0);
//         }
//         bb.put(bytes, 0, 8-padZeros);
//         bb.flip();
//         return bb.getLong();
//     }
//     
//     public static byte[] intToBytes(int x) {
//         ByteBuffer bb = ByteBuffer.allocate(4);
//         bb.putInt(x);
//         return bb.array();
//     }
// 
//     public static int bytesToInt(byte[] bytes) {
//         return ByteBuffer.wrap(bytes).getInt();
//     }
// 
//     public static byte[] leastSignificantBytes(long l, int numBytes) {
//         byte[] all8Bytes = Util.longToBytes(l);
//         return trailingBytes(all8Bytes, numBytes);
//     }
// 
//     public static byte[] trailingBytes(byte[] bs, int numBytes) {
//         return Arrays.copyOfRange(bs, bs.length-numBytes, bs.length);
//     }
// 
//     /**
//      * A utility to allow hashing of a portion of an array without having to copy it.
//      * @param array
//      * @param startInclusive
//      * @param endExclusive
//      * @return hash byte
//      */
//     public static byte hashByteArray(byte[] array, int startInclusive, int endExclusive) {
//         if (array == null) {
//             return 0;
//         }
// 
//         int range = endExclusive - startInclusive;
//         if (range < 0) {
//             throw new IllegalArgumentException(startInclusive + " > " + endExclusive);
//         }
// 
//         int result = 1;
//         for (int i=startInclusive; i<endExclusive; i++){
//             result = 31 * result + array[i];
//         }
// 
//         return (byte)result;
//     }
//     
//     /**
//      * Only use this for testing/debugging. Inefficient.
//      */
//     public static long countRows(Configuration conf, byte[] tableName) throws IOException {
//         HTable hTable = null;
//         ResultScanner rs = null;
//         long count = 0;
//         try {
//             hTable = new HTable(conf, tableName);
//             rs = hTable.getScanner(new Scan());
//             for(@SuppressWarnings("unused") Result r: rs) {
//                 count++;
//             }
//             return count;
//         } finally {
//             if(hTable != null) {
//                 hTable.close();
//             }
//             if(rs != null) {
//                 rs.close();
//             }
//         }
//     }
// }


import com.urbanairship.datacube.CSerializable;
import com.urbanairship.datacube.Util;
/*
Copyright 2012 Urban Airship and Contributors
*/

package com.urbanairship.datacube.serializables;


/**
 * When using an enum as a dimension bucket type, this wrapper eliminates the boilerplate
 * of serializing it to an ordinal. Use this in your bucketer.
 */
public class EnumSerializable implements CSerializable {
    private final int ordinal;
    private final int numFieldBytes;

    /**
     * @param numFieldBytes the number of bytes to produce for serialized version of this
     *                      enum
     */
    public EnumSerializable(Enum<?> enumInstance, int numFieldBytes) {
        this.ordinal = enumInstance.ordinal();
        this.numFieldBytes = numFieldBytes;

        if (numFieldBytes < 1 || numFieldBytes > 4) {
            throw new IllegalArgumentException("numFieldBytes must be in [1..4]");
        }
    }

    @Override
    public byte[] serialize() {
        return staticSerialize(ordinal, numFieldBytes);
    }

    public static byte[] staticSerialize(Enum<?> enumInstance, int numFieldBytes) {
        return staticSerialize(enumInstance.ordinal(), numFieldBytes);
    }

    public static byte[] staticSerialize(int ordinal, int numFieldBytes) {
// Path: src/main/java/com/urbanairship/datacube/CSerializable.java
// public interface CSerializable {
//     byte[] serialize();
// }
// 
// Path: src/main/java/com/urbanairship/datacube/Util.java
// public class Util {
//     public static byte[] longToBytes(long l) {
//         return ByteBuffer.allocate(8).putLong(l).array();
//     }
// 
//     /**
//      * Write a big-endian integer into the least significant bytes of a byte array.
//      */
//     public static byte[] intToBytesWithLen(int x, int len) {
//         if(len <= 4) {
//             return trailingBytes(intToBytes(x), len);
//         } else {
//             ByteBuffer bb = ByteBuffer.allocate(len);
//             bb.position(len-4);
//             bb.putInt(x);
//             assert bb.remaining() == 0;
//             return bb.array();
//         }
//     }
// 
//     public static long bytesToLong(byte[] bytes) {
//         if(bytes.length < 8) {
//             throw new IllegalArgumentException("Input array was too small: " +
//                     Arrays.toString(bytes));
//         }
//         
//         return ByteBuffer.wrap(bytes).getLong();
//     }
//     
//     /**
//      * Call this if you have a byte array to convert to long, but your array might need
//      * to be left-padded with zeros (if it is less than 8 bytes long). 
//      */
//     public static long bytesToLongPad(byte[] bytes) {
//         final int padZeros = Math.max(8-bytes.length, 0);
//         ByteBuffer bb = ByteBuffer.allocate(8);
//         for(int i=0; i<padZeros; i++) {
//             bb.put((byte)0);
//         }
//         bb.put(bytes, 0, 8-padZeros);
//         bb.flip();
//         return bb.getLong();
//     }
//     
//     public static byte[] intToBytes(int x) {
//         ByteBuffer bb = ByteBuffer.allocate(4);
//         bb.putInt(x);
//         return bb.array();
//     }
// 
//     public static int bytesToInt(byte[] bytes) {
//         return ByteBuffer.wrap(bytes).getInt();
//     }
// 
//     public static byte[] leastSignificantBytes(long l, int numBytes) {
//         byte[] all8Bytes = Util.longToBytes(l);
//         return trailingBytes(all8Bytes, numBytes);
//     }
// 
//     public static byte[] trailingBytes(byte[] bs, int numBytes) {
//         return Arrays.copyOfRange(bs, bs.length-numBytes, bs.length);
//     }
// 
//     /**
//      * A utility to allow hashing of a portion of an array without having to copy it.
//      * @param array
//      * @param startInclusive
//      * @param endExclusive
//      * @return hash byte
//      */
//     public static byte hashByteArray(byte[] array, int startInclusive, int endExclusive) {
//         if (array == null) {
//             return 0;
//         }
// 
//         int range = endExclusive - startInclusive;
//         if (range < 0) {
//             throw new IllegalArgumentException(startInclusive + " > " + endExclusive);
//         }
// 
//         int result = 1;
//         for (int i=startInclusive; i<endExclusive; i++){
//             result = 31 * result + array[i];
//         }
// 
//         return (byte)result;
//     }
//     
//     /**
//      * Only use this for testing/debugging. Inefficient.
//      */
//     public static long countRows(Configuration conf, byte[] tableName) throws IOException {
//         HTable hTable = null;
//         ResultScanner rs = null;
//         long count = 0;
//         try {
//             hTable = new HTable(conf, tableName);
//             rs = hTable.getScanner(new Scan());
//             for(@SuppressWarnings("unused") Result r: rs) {
//                 count++;
//             }
//             return count;
//         } finally {
//             if(hTable != null) {
//                 hTable.close();
//             }
//             if(rs != null) {
//                 rs.close();
//             }
//         }
//     }
// }


// Path: src/main/java/com/urbanairship/datacube/serializables/EnumSerializable.java
import com.urbanairship.datacube.CSerializable;
import com.urbanairship.datacube.Util;

/*
Copyright 2012 Urban Airship and Contributors
*/

package com.urbanairship.datacube.serializables;


/**
 * When using an enum as a dimension bucket type, this wrapper eliminates the boilerplate
 * of serializing it to an ordinal. Use this in your bucketer.
 */
public class EnumSerializable implements CSerializable {
    private final int ordinal;
    private final int numFieldBytes;

    /**
     * @param numFieldBytes the number of bytes to produce for serialized version of this
     *                      enum
     */
    public EnumSerializable(Enum<?> enumInstance, int numFieldBytes) {
        this.ordinal = enumInstance.ordinal();
        this.numFieldBytes = numFieldBytes;

        if (numFieldBytes < 1 || numFieldBytes > 4) {
            throw new IllegalArgumentException("numFieldBytes must be in [1..4]");
        }
    }

    @Override
    public byte[] serialize() {
        return staticSerialize(ordinal, numFieldBytes);
    }

    public static byte[] staticSerialize(Enum<?> enumInstance, int numFieldBytes) {
        return staticSerialize(enumInstance.ordinal(), numFieldBytes);
    }

    public static byte[] staticSerialize(int ordinal, int numFieldBytes) {
        return Util.intToBytesWithLen(ordinal, numFieldBytes);