use of io.cdap.cdap.common.io.Encoder in project cdap by caskdata.
the class CodecTest method testCodec.
@Test
public void testCodec() throws IOException {
PipedOutputStream output = new PipedOutputStream();
PipedInputStream input = new PipedInputStream(output);
Encoder encoder = new BinaryEncoder(output);
Decoder decoder = new BinaryDecoder(input);
encoder.writeNull();
Assert.assertNull(decoder.readNull());
encoder.writeBool(true);
Assert.assertTrue(decoder.readBool());
encoder.writeBool(false);
Assert.assertFalse(decoder.readBool());
encoder.writeInt(0);
Assert.assertEquals(0, decoder.readInt());
encoder.writeInt(-1);
Assert.assertEquals(-1, decoder.readInt());
encoder.writeInt(1234);
Assert.assertEquals(1234, decoder.readInt());
encoder.writeInt(-1234);
Assert.assertEquals(-1234, decoder.readInt());
encoder.writeInt(Short.MAX_VALUE);
Assert.assertEquals(Short.MAX_VALUE, decoder.readInt());
encoder.writeInt(Short.MIN_VALUE);
Assert.assertEquals(Short.MIN_VALUE, decoder.readInt());
encoder.writeInt(Integer.MAX_VALUE);
Assert.assertEquals(Integer.MAX_VALUE, decoder.readInt());
encoder.writeInt(Integer.MIN_VALUE);
Assert.assertEquals(Integer.MIN_VALUE, decoder.readInt());
encoder.writeLong(0);
Assert.assertEquals(0, decoder.readLong());
encoder.writeLong(-20);
Assert.assertEquals(-20, decoder.readLong());
encoder.writeLong(30000);
Assert.assertEquals(30000, decoder.readLong());
encoder.writeLong(-600000);
Assert.assertEquals(-600000, decoder.readLong());
encoder.writeLong(Integer.MAX_VALUE);
Assert.assertEquals(Integer.MAX_VALUE, decoder.readLong());
encoder.writeLong(Integer.MIN_VALUE);
Assert.assertEquals(Integer.MIN_VALUE, decoder.readLong());
encoder.writeLong(Long.MAX_VALUE);
Assert.assertEquals(Long.MAX_VALUE, decoder.readLong());
encoder.writeLong(Long.MIN_VALUE);
Assert.assertEquals(Long.MIN_VALUE, decoder.readLong());
encoder.writeFloat(3.14f);
Assert.assertEquals(3.14f, decoder.readFloat(), 0.0000001f);
encoder.writeFloat(Short.MAX_VALUE);
Assert.assertEquals(Short.MAX_VALUE, decoder.readFloat(), 0.0000001f);
encoder.writeFloat(Integer.MIN_VALUE);
Assert.assertEquals(Integer.MIN_VALUE, decoder.readFloat(), 0.0000001f);
encoder.writeFloat((long) Integer.MAX_VALUE * Short.MAX_VALUE);
Assert.assertEquals((long) Integer.MAX_VALUE * Short.MAX_VALUE, decoder.readFloat(), 0.0000001f);
encoder.writeFloat(Float.MAX_VALUE);
Assert.assertEquals(Float.MAX_VALUE, decoder.readFloat(), 0.0000001f);
encoder.writeFloat(Float.MIN_VALUE);
Assert.assertEquals(Float.MIN_VALUE, decoder.readFloat(), 0.0000001f);
encoder.writeDouble(Math.E);
Assert.assertEquals(Math.E, decoder.readDouble(), 0.0000001f);
encoder.writeDouble(Integer.MAX_VALUE);
Assert.assertEquals(Integer.MAX_VALUE, decoder.readDouble(), 0.0000001f);
encoder.writeDouble(Long.MIN_VALUE);
Assert.assertEquals(Long.MIN_VALUE, decoder.readDouble(), 0.0000001f);
encoder.writeDouble((long) Integer.MAX_VALUE * Short.MAX_VALUE);
Assert.assertEquals((long) Integer.MAX_VALUE * Short.MAX_VALUE, decoder.readDouble(), 0.0000001f);
encoder.writeDouble(Double.MAX_VALUE);
Assert.assertEquals(Double.MAX_VALUE, decoder.readDouble(), 0.0000001f);
encoder.writeDouble(Double.MIN_VALUE);
Assert.assertEquals(Double.MIN_VALUE, decoder.readDouble(), 0.0000001f);
encoder.writeString("This is a testing message");
Assert.assertEquals("This is a testing message", decoder.readString());
String str = Character.toString((char) 200) + Character.toString((char) 20000) + Character.toString((char) 40000);
encoder.writeString(str);
Assert.assertEquals(str, decoder.readString());
ByteBuffer buf = ByteBuffer.allocate(12);
buf.asIntBuffer().put(10).put(1024).put(9999999);
encoder.writeBytes(buf);
IntBuffer inBuf = decoder.readBytes().asIntBuffer();
Assert.assertEquals(10, inBuf.get());
Assert.assertEquals(1024, inBuf.get());
Assert.assertEquals(9999999, inBuf.get());
}
use of io.cdap.cdap.common.io.Encoder in project cdap by caskdata.
the class DatumWriterGenerator method getEncodeMethod.
/**
* Returns the encode method for the given type and schema. The same method will be returned if the same
* type and schema has been passed to the method before.
*
* @param outputType Type information of the data type for output
* @param schema Schema to use for output.
* @return A method for encoding the given output type and schema.
*/
private Method getEncodeMethod(TypeToken<?> outputType, Schema schema) {
String key = String.format("%s%s", normalizeTypeName(outputType), schema.getSchemaHash());
Method method = encodeMethods.get(key);
if (method != null) {
return method;
}
// Generate the encode method (value, encoder, schema, set)
TypeToken<?> callOutputType = getCallTypeToken(outputType, schema);
String methodName = String.format("encode%s", key);
method = getMethod(void.class, methodName, callOutputType.getRawType(), Encoder.class, Schema.class, Set.class);
// Put the method into map first before generating the body in order to support recursive data type.
encodeMethods.put(key, method);
String methodSignature = Signatures.getMethodSignature(method, TypeToken.of(void.class), callOutputType, null, null, new TypeToken<Set<Object>>() {
});
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PRIVATE, method, methodSignature, new Type[] { Type.getType(IOException.class) }, classWriter);
generateEncodeBody(mg, schema, outputType, 0, 1, 2, 3);
mg.returnValue();
mg.endMethod();
return method;
}
use of io.cdap.cdap.common.io.Encoder in project cdap by caskdata.
the class DatumWriterGenerator method encodeMap.
/**
* Generates method body for encoding map value. The logic is like this:
*
* <pre>
* {@code
*
* encoder.writeInt(map.size();
*
* for (Map.Entry<Key, Value> entry : map.entrySet()) {
* encodeKey(entry.getKey(), encoder, keySchema, seenRefs);
* encodeValue(entry.getValue(), encoder, valueSchema, seenRefs);
* }
*
* if (map.size() > 0) {
* encoder.writeInt(0);
* }
* }
* </pre>
*
* @param mg
* @param keyType
* @param valueType
* @param keySchema
* @param valueSchema
* @param value
* @param encoder
* @param schemaLocal
* @param seenRefs
*/
private void encodeMap(GeneratorAdapter mg, TypeToken<?> keyType, TypeToken<?> valueType, Schema keySchema, Schema valueSchema, int value, int encoder, int schemaLocal, int seenRefs) {
// Encode and store the map length locally
mg.loadArg(value);
mg.invokeInterface(Type.getType(Map.class), getMethod(int.class, "size"));
int length = mg.newLocal(Type.INT_TYPE);
mg.storeLocal(length);
mg.loadArg(encoder);
mg.loadLocal(length);
mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class));
mg.pop();
// Stores the key and value schema
mg.loadArg(schemaLocal);
mg.invokeVirtual(Type.getType(Schema.class), getMethod(Map.Entry.class, "getMapSchema"));
mg.dup();
int keySchemaLocal = mg.newLocal(Type.getType(Schema.class));
mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getKey"));
mg.checkCast(Type.getType(Schema.class));
mg.storeLocal(keySchemaLocal);
int valueSchemaLocal = mg.newLocal(Type.getType(Schema.class));
mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getValue"));
mg.checkCast(Type.getType(Schema.class));
mg.storeLocal(valueSchemaLocal);
// Store the entry set iterator
int iterator = mg.newLocal(Type.getType(Iterator.class));
mg.loadArg(value);
mg.invokeInterface(Type.getType(Map.class), getMethod(Set.class, "entrySet"));
mg.invokeInterface(Type.getType(Set.class), getMethod(Iterator.class, "iterator"));
mg.storeLocal(iterator);
// For loop the entry set iterator, encode each key-value pairs
Label beginFor = mg.mark();
Label endFor = mg.newLabel();
mg.loadLocal(iterator);
mg.invokeInterface(Type.getType(Iterator.class), getMethod(boolean.class, "hasNext"));
mg.ifZCmp(GeneratorAdapter.EQ, endFor);
int entry = mg.newLocal(Type.getType(Map.Entry.class));
mg.loadLocal(iterator);
mg.invokeInterface(Type.getType(Iterator.class), getMethod(Object.class, "next"));
mg.checkCast(Type.getType(Map.Entry.class));
mg.storeLocal(entry);
// encode key
mg.loadThis();
mg.loadLocal(entry);
mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getKey"));
doCast(mg, keyType, keySchema);
mg.loadArg(encoder);
mg.loadLocal(keySchemaLocal);
mg.loadArg(seenRefs);
mg.invokeVirtual(classType, getEncodeMethod(keyType, keySchema));
// encode value
mg.loadThis();
mg.loadLocal(entry);
mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getValue"));
doCast(mg, valueType, valueSchema);
mg.loadArg(encoder);
mg.loadLocal(valueSchemaLocal);
mg.loadArg(seenRefs);
mg.invokeVirtual(classType, getEncodeMethod(valueType, valueSchema));
mg.goTo(beginFor);
mg.mark(endFor);
// if length > 0, write out 0 at the end of map
Label zeroLength = mg.newLabel();
mg.loadLocal(length);
mg.ifZCmp(GeneratorAdapter.LE, zeroLength);
encodeInt(mg, 0, encoder);
mg.mark(zeroLength);
}
use of io.cdap.cdap.common.io.Encoder in project cdap by caskdata.
the class DatumWriterGenerator method encodeArray.
/**
* Generates method body for encoding array value. The logic is similar to the one in
* {@link #encodeCollection}, with collection size replaced with array length.
*
* @param mg
* @param componentType
* @param componentSchema
* @param value
* @param encoder
* @param schemaLocal
* @param seenRefs
*/
private void encodeArray(GeneratorAdapter mg, TypeToken<?> componentType, Schema componentSchema, int value, int encoder, int schemaLocal, int seenRefs) {
// Encode and store the array length locally
mg.loadArg(value);
mg.arrayLength();
int length = mg.newLocal(Type.INT_TYPE);
mg.storeLocal(length);
mg.loadArg(encoder);
mg.loadLocal(length);
mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class));
mg.pop();
// Store the component schema
mg.loadArg(schemaLocal);
mg.invokeVirtual(Type.getType(Schema.class), getMethod(Schema.class, "getComponentSchema"));
int componentSchemaLocal = mg.newLocal(Type.getType(Schema.class));
mg.storeLocal(componentSchemaLocal);
// for (int idx = 0; idx < array.length; idx++)
mg.push(0);
int idx = mg.newLocal(Type.INT_TYPE);
mg.storeLocal(idx);
Label beginFor = mg.mark();
Label endFor = mg.newLabel();
mg.loadLocal(idx);
mg.loadLocal(length);
mg.ifICmp(GeneratorAdapter.GE, endFor);
// Call encode method to encode array[idx]
mg.loadThis();
mg.loadArg(value);
mg.loadLocal(idx);
TypeToken<?> callTypeToken = getCallTypeToken(componentType, componentSchema);
mg.arrayLoad(Type.getType(callTypeToken.getRawType()));
mg.loadArg(encoder);
mg.loadLocal(componentSchemaLocal);
mg.loadArg(seenRefs);
mg.invokeVirtual(classType, getEncodeMethod(componentType, componentSchema));
mg.iinc(idx, 1);
mg.goTo(beginFor);
mg.mark(endFor);
// if length > 0, write out 0 at the end of array.
Label zeroLength = mg.newLabel();
mg.loadLocal(length);
mg.ifZCmp(GeneratorAdapter.LE, zeroLength);
encodeInt(mg, 0, encoder);
mg.mark(zeroLength);
}
use of io.cdap.cdap.common.io.Encoder in project cdap by caskdata.
the class UserIdentityCodec method encode.
@Override
public byte[] encode(UserIdentity identifier) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Encoder encoder = new BinaryEncoder(bos);
encoder.writeInt(UserIdentity.Schemas.getVersion());
DatumWriter<UserIdentity> writer = writerFactory.create(ACCESS_TOKEN_IDENTIFIER_TYPE, UserIdentity.Schemas.getCurrentSchema());
writer.encode(identifier, encoder);
return bos.toByteArray();
}
Aggregations