package org.yamcs.yarch.rocksdb;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.yamcs.yarch.DataType;
import org.yamcs.yarch.TableDefinition;
/**
* Used in partitioning by value - each value is a different column family
*
* @author nm
*
*/
public class ColumnValueSerializer implements ColumnFamilySerializer {
private final DataType valuePartitionDataType;
public final static byte[] NULL_COLUMN_FAMILY = {};
public ColumnValueSerializer(DataType dt) {
this.valuePartitionDataType = dt;
}
public ColumnValueSerializer(TableDefinition tableDefinition) {
this(tableDefinition.getPartitioningSpec().getValueColumnType());
}
public byte[] objectToByteArray(Object value) {
if(value==null) return NULL_COLUMN_FAMILY;
if(value.getClass()==Integer.class) {
ByteBuffer bb = ByteBuffer.allocate(4);
bb.putInt((Integer)value);
return bb.array();
} else if(value.getClass()==Short.class) {
ByteBuffer bb = ByteBuffer.allocate(2);
bb.putShort((Short)value);
return bb.array();
} else if(value.getClass()==Byte.class) {
ByteBuffer bb = ByteBuffer.allocate(1);
bb.put((Byte)value);
return bb.array();
} else if(value.getClass()==String.class) {
return ((String)value).getBytes();
} else {
throw new IllegalArgumentException("partition on values of type "+value.getClass()+" not supported");
}
}
/**
* this is the reverse of the {@link #objectToByteArray(Object value)}
*/
public Object byteArrayToObject(byte[] b) {
if(Arrays.equals(b, NULL_COLUMN_FAMILY)) return null;
DataType dt = valuePartitionDataType;
switch(dt.val) {
case INT:
if(b.length!=4) throw new IllegalArgumentException("unexpected buffer of size "+b.length+" for a partition of type "+dt);
ByteBuffer bb = ByteBuffer.wrap(b);
return bb.getInt();
case SHORT:
case ENUM: //intentional fall-through
if(b.length!=2) throw new IllegalArgumentException("unexpected buffer of size "+b.length+" for a partition of type "+dt);
bb = ByteBuffer.wrap(b);
return bb.getShort();
case BYTE:
if(b.length!=1) throw new IllegalArgumentException("unexpected buffer of size "+b.length+" for a partition of type "+dt);
bb = ByteBuffer.wrap(b);
return bb.get();
case STRING:
return new String(b);
default:
throw new IllegalArgumentException("partition on values of type "+dt+" not supported");
}
}
/**
* return the size in bytes of the encoded data type if it can be encoded on fixed size, or -1 if not.
* @param dt
* @return
*/
public static int getSerializedSize(DataType dt) {
switch(dt.val) {
case INT:
return 4;
case SHORT:
case ENUM: //intentional fall-through
return 2;
case BYTE:
case BOOLEAN: //intentional fall-through
return 1;
case DOUBLE:
case TIMESTAMP: //intentional fall-through
return 8;
default:
return -1;
}
}
}