in java/fury-core/src/main/java/org/apache/fury/builder/ObjectCodecBuilder.java [310:408]
private List<Expression> serializePrimitivesCompressed(
Expression bean, Expression buffer, List<List<Descriptor>> primitiveGroups, int totalSize) {
List<Expression> expressions = new ArrayList<>();
// int/long may need extra one-byte for writing.
int extraSize = 0;
for (List<Descriptor> group : primitiveGroups) {
for (Descriptor d : group) {
if (d.getRawType() == int.class) {
// varint may be written as 5bytes, use 8bytes for written as long to reduce cost.
extraSize += 4;
} else if (d.getRawType() == long.class) {
extraSize += 1; // long use 1~9 bytes.
}
}
}
int growSize = totalSize + extraSize;
// After this grow, following writes can be unsafe without checks.
expressions.add(new Invoke(buffer, "grow", Literal.ofInt(growSize)));
// Must grow first, otherwise may get invalid address.
Expression base = new Invoke(buffer, "getHeapMemory", "base", PRIMITIVE_BYTE_ARRAY_TYPE);
expressions.add(base);
int numPrimitiveFields = getNumPrimitiveFields(primitiveGroups);
for (List<Descriptor> group : primitiveGroups) {
ListExpression groupExpressions = new ListExpression();
Expression writerAddr =
new Invoke(buffer, "_unsafeWriterAddress", "writerAddr", PRIMITIVE_LONG_TYPE);
// use Reference to cut-off expr dependency.
int acc = 0;
boolean compressStarted = false;
for (Descriptor descriptor : group) {
Class<?> clz = descriptor.getRawType();
Preconditions.checkArgument(isPrimitive(clz));
// `bean` will be replaced by `Reference` to cut-off expr dependency.
Expression fieldValue = getFieldValue(bean, descriptor);
if (fieldValue instanceof Inlineable) {
((Inlineable) fieldValue).inline();
}
if (clz == byte.class) {
groupExpressions.add(unsafePut(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 1;
} else if (clz == boolean.class) {
groupExpressions.add(unsafePutBoolean(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 1;
} else if (clz == char.class) {
groupExpressions.add(unsafePutChar(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 2;
} else if (clz == short.class) {
groupExpressions.add(unsafePutShort(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 2;
} else if (clz == float.class) {
groupExpressions.add(unsafePutFloat(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 4;
} else if (clz == double.class) {
groupExpressions.add(unsafePutDouble(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 8;
} else if (clz == int.class) {
if (!fury.compressInt()) {
groupExpressions.add(unsafePutInt(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 4;
} else {
if (!compressStarted) {
// int/long are sorted in the last.
addIncWriterIndexExpr(groupExpressions, buffer, acc);
compressStarted = true;
}
groupExpressions.add(new Invoke(buffer, "_unsafeWriteVarInt32", fieldValue));
acc += 0;
}
} else if (clz == long.class) {
if (!fury.compressLong()) {
groupExpressions.add(unsafePutLong(base, getWriterPos(writerAddr, acc), fieldValue));
acc += 8;
} else {
if (!compressStarted) {
// int/long are sorted in the last.
addIncWriterIndexExpr(groupExpressions, buffer, acc);
compressStarted = true;
}
groupExpressions.add(
LongSerializer.writeInt64(buffer, fieldValue, fury.longEncoding(), false));
}
} else {
throw new IllegalStateException("impossible");
}
}
if (!compressStarted) {
// int/long are sorted in the last.
addIncWriterIndexExpr(groupExpressions, buffer, acc);
}
if (numPrimitiveFields < 4) {
expressions.add(groupExpressions);
} else {
expressions.add(
objectCodecOptimizer.invokeGenerated(
ofHashSet(bean, buffer, base), groupExpressions, "writeFields"));
}
}
return expressions;
}