public byte[] asBytes() {
    if (_values.length == 1) {
      return asBytesSingleVal(_values[0]);
    }

    int sizeInBytes = 0;
    byte[][] cache = new byte[_values.length][];
    for (int i = 0; i < _values.length; i++) {
      Object value = _values[i];

      if (value instanceof Integer) {
        sizeInBytes += Integer.BYTES;
      } else if (value instanceof Long) {
        sizeInBytes += Long.BYTES;
      } else if (value instanceof String) {
        cache[i] = ((String) value).getBytes(StandardCharsets.UTF_8);
        sizeInBytes += cache[i].length + Integer.BYTES;
      } else if (value instanceof ByteArray) {
        cache[i] = ((ByteArray) value).getBytes();
        sizeInBytes += cache[i].length + Integer.BYTES;
      } else if (value instanceof Float) {
        sizeInBytes += Float.BYTES;
      } else if (value instanceof Double) {
        sizeInBytes += Double.BYTES;
      } else if (value instanceof BigDecimal) {
        cache[i] = BigDecimalUtils.serialize((BigDecimal) value);
        sizeInBytes += cache[i].length + Integer.BYTES;
      } else {
        throw new IllegalStateException(
            String.format("Unsupported value: %s of type: %s", value, value != null ? value.getClass() : null));
      }
    }

    ByteBuffer byteBuffer = ByteBuffer.allocate(sizeInBytes);
    for (int i = 0; i < _values.length; i++) {
      Object value = _values[i];

      if (value instanceof Integer) {
        byteBuffer.putInt((Integer) value);
      } else if (value instanceof Long) {
        byteBuffer.putLong((Long) value);
      } else if (value instanceof Float) {
        byteBuffer.putFloat((Float) value);
      } else if (value instanceof Double) {
        byteBuffer.putDouble((Double) value);
      } else {
        byteBuffer.putInt(cache[i].length);
        byteBuffer.put(cache[i]);
      }
    }
    return byteBuffer.array();
  }
@Test
  public void testSerialization() {
    byte[] rawbytes = {0xa, 0x2, (byte) 0xff};
    Object[] values = new Object[]{
        "foo_bar", 2, 2.0d, 3.14f, System.currentTimeMillis(), new ByteArray(rawbytes), new BigDecimal(100)
    };
    PrimaryKey pk = new PrimaryKey(values);
    byte[] bytes = pk.asBytes();
    ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);

    int length = byteBuffer.getInt();
    assertEquals(length, ((String) values[0]).length());
    byte[] arr = new byte[length];
    byteBuffer.get(arr);
    String out = new String(arr, StandardCharsets.UTF_8);
    assertEquals(out, values[0]);

    assertEquals(byteBuffer.getInt(), values[1]);
    assertEquals(byteBuffer.getDouble(), values[2]);
    assertEquals(byteBuffer.getFloat(), values[3]);
    assertEquals(byteBuffer.getLong(), values[4]);

    assertEquals(byteBuffer.getInt(), rawbytes.length);
    arr = new byte[rawbytes.length];
    byteBuffer.get(arr);
    assertEquals(arr, rawbytes);

    length = byteBuffer.getInt();
    arr = new byte[length];
    byteBuffer.get(arr);
    assertEquals(BigDecimalUtils.deserialize(arr), values[6]);
  }